def selectDatasource(self): """ Opens dialog for file/directory selection. """ # model of implementation for reimplementation fd = QFileDialog() fd.setFileMode(QFileDialog.Directory) fd.setOption(QFileDialog.ShowDirsOnly, True) directory = fd.getExistingDirectory(caption=self.selectionWidget.connectionSelectorLineEdit.caption) if directory: if len(directory) > 4: # datasource connection name for a shape 'database' is its parent folder directory = directory if directory[-4:].lower() != '.shp' else directory[:-4] # set only directories as line text self.selectionWidget.connectionSelectorLineEdit.lineEdit.setText(directory) self.selectionWidget.loadDatabase(currentText=directory)
def upload_data(self): if self.check_login(): if self.local_data_sources.count() == 0: return if self.db_connections.count() == 0: QMessageBox.warning(self, self.tr("No database available"), self.tr("Please create a database in the 'Account' tab.")) return if not self.ui.cbUploadDatabase.currentIndex() >= 0: QMessageBox.warning(self, self.tr("No database selected"), self.tr("Please select a database to upload data.")) return db_name = self.ui.cbUploadDatabase.currentText() if not self.db_connections.isPortOpen(db_name): uri = self.db_connections.cloud_layer_uri(db_name, "", "") host = str(uri.host()) port = uri.port() QMessageBox.critical(self, self.tr("Network Error"), self.tr("Could not connect to database server ({0}) on port {1}. Please contact your system administrator or internet provider to open port {1} in the firewall".format(host, port))) return # disable update of local data sources during upload, as there are # temporary layers added and removed self.do_update_local_data_sources = False self.statusBar().showMessage(self.tr("Uploading data...")) self.setCursor(Qt.WaitCursor) self.ui.btnUploadData.hide() self.ui.spinner.start() self.ui.progressWidget.show() # Map<data_source, {table: table, layers: layers}> data_sources_items = {} for row in range(0, self.ui.tblLocalLayers.rowCount()): data_source = unicode( self.ui.tblLocalLayers.item( row, self.COLUMN_DATA_SOURCE).text()) layers = self.local_data_sources.layers(data_source) if layers is not None: table_name = unicode( self.ui.tblLocalLayers.item( row, self.COLUMN_TABLE_NAME).text()) data_sources_items[data_source] = { u'table': unicode(table_name), u'layers': layers} login_info = self.api.check_login(version_info=self._version_info()) try: self.maxSize = login_info['max_storage'] self.maxDBs = login_info['max_dbs'] except: self.maxSize = 50 self.maxDBs = 5 try: self.data_upload.upload(self.db_connections.db(unicode(db_name)), data_sources_items, unicode(self.maxSize)) upload_ok = True except Exception as e: ErrorReportDialog(self.tr("Upload errors occurred"), self.tr("Upload errors occurred. Not all data could be uploaded."), str(e) + "\n" + traceback.format_exc(), self.user, self).exec_() upload_ok = False self.ui.spinner.stop() self.ui.progressWidget.hide() self.ui.btnUploadData.show() self.unsetCursor() self.statusBar().showMessage("") # Refresh local layers self.do_update_local_data_sources = True self.update_local_layers() # Refresh used space after upload self.db_size(self.db_connections) if upload_ok: # Show save project dialog save_dialog = QDialog(self) save_dialog.setWindowTitle(self.tr("Save Project")) save_dialog.setLayout(QVBoxLayout()) header = QWidget() header.setLayout(QVBoxLayout()) label = QLabel(self.tr("Upload complete. The local layers in the project were replaced with the layers uploaded to the qgiscloud database.")) label.setWordWrap(True) header.layout().addWidget(label) label = QLabel(self.tr("Choose were to save the modified project:")) label.setWordWrap(True) header.layout().addWidget(label) save_dialog.layout().setContentsMargins(0, 0, 0, 0) save_dialog.layout().addWidget(header) initialPath = QgsProject.instance().fileName() if not initialPath: initialPath = QSettings().value("/UI/lastProjectDir", ".") fd = QFileDialog(None, self.tr("Save Project"), initialPath, "%s (*.qgz *.qgs)" % self.tr("QGIS Project Files")) fd.setParent(save_dialog, Qt.Widget) fd.setOption(QFileDialog.DontUseNativeDialog) fd.setAcceptMode(QFileDialog.AcceptSave) save_dialog.layout().addWidget(fd) header.layout().setContentsMargins(fd.layout().contentsMargins()) fd.accepted.connect(save_dialog.accept) fd.rejected.connect(save_dialog.reject) if save_dialog.exec_() == QDialog.Accepted: files = list(fd.selectedFiles()) if files: QgsProject.instance().setFileName(files[0]) self.iface.actionSaveProject().trigger() # Switch to map tab self.ui.tabWidget.setCurrentWidget(self.ui.mapTab)
class TreeGenerator(object): """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'TreeGenerator_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = TreeGeneratorDialog() self.dlg.runButton.clicked.connect(self.start_progress) self.dlg.pushButtonSave.clicked.connect(self.folder_path) self.dlg.helpButton.clicked.connect(self.help) self.fileDialog = QFileDialog() # self.fileDialog.setFileMode(4) # self.fileDialog.setAcceptMode(1) self.fileDialog.setFileMode(QFileDialog.Directory) self.fileDialog.setOption(QFileDialog.ShowDirsOnly, True) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Tree Generator') # TODO: We are going to let the user set this up in a future iteration # self.toolbar = self.iface.addToolBar(u'TreeGenerator') # self.toolbar.setObjectName(u'TreeGenerator') # self.layerComboManagerPoint = VectorLayerCombo(self.dlg.comboBox_pointlayer) # fieldgen = VectorLayerCombo(self.dlg.comboBox_pointlayer, initLayer="", options={"geomType": QGis.Point}) # self.layerComboManagerTreeTypeField = FieldCombo(self.dlg.comboBox_ttype, fieldgen, initField="") # self.layerComboManagerTotalHeightField = FieldCombo(self.dlg.comboBox_totalheight, fieldgen, initField="") # self.layerComboManagerTrunkHeightField = FieldCombo(self.dlg.comboBox_trunkheight, fieldgen, initField="") # self.layerComboManagerDiameterField = FieldCombo(self.dlg.comboBox_diameter, fieldgen, initField="") self.layerComboManagerPoint = QgsMapLayerComboBox(self.dlg.widgetPointLayer) self.layerComboManagerPoint.setCurrentIndex(-1) self.layerComboManagerPoint.setFilters(QgsMapLayerProxyModel.PointLayer) self.layerComboManagerPoint.setFixedWidth(175) self.layerComboManagerTreeTypeField = QgsFieldComboBox(self.dlg.widgetTreeType) self.layerComboManagerTreeTypeField.setFilters(QgsFieldProxyModel.Numeric) self.layerComboManagerPoint.layerChanged.connect(self.layerComboManagerTreeTypeField.setLayer) self.layerComboManagerTotalHeightField = QgsFieldComboBox(self.dlg.widgetTotalHeight) self.layerComboManagerTotalHeightField.setFilters(QgsFieldProxyModel.Numeric) self.layerComboManagerPoint.layerChanged.connect(self.layerComboManagerTotalHeightField.setLayer) self.layerComboManagerTrunkHeightField = QgsFieldComboBox(self.dlg.widgetTrunkHeight) self.layerComboManagerTrunkHeightField.setFilters(QgsFieldProxyModel.Numeric) self.layerComboManagerPoint.layerChanged.connect(self.layerComboManagerTrunkHeightField.setLayer) self.layerComboManagerDiameterField = QgsFieldComboBox(self.dlg.widgetDiameter) self.layerComboManagerDiameterField.setFilters(QgsFieldProxyModel.Numeric) self.layerComboManagerPoint.layerChanged.connect(self.layerComboManagerDiameterField.setLayer) # self.layerComboManagerDSM = RasterLayerCombo(self.dlg.comboBox_DSM) # RasterLayerCombo(self.dlg.comboBox_DSM, initLayer="") # self.layerComboManagerDEM = RasterLayerCombo(self.dlg.comboBox_DEM) # RasterLayerCombo(self.dlg.comboBox_DEM, initLayer="") # self.layerComboManagerBuild = RasterLayerCombo(self.dlg.comboBox_Build) # RasterLayerCombo(self.dlg.comboBox_Build, initLayer="") # self.layerComboManagerCDSM = RasterLayerCombo(self.dlg.comboBox_CDSM) # RasterLayerCombo(self.dlg.comboBox_CDSM, initLayer="") # self.layerComboManagerTDSM = RasterLayerCombo(self.dlg.comboBox_TDSM) # RasterLayerCombo(self.dlg.comboBox_TDSM, initLayer="") self.layerComboManagerDSM = QgsMapLayerComboBox(self.dlg.widgetDSM) self.layerComboManagerDSM.setFilters(QgsMapLayerProxyModel.RasterLayer) self.layerComboManagerDSM.setFixedWidth(175) self.layerComboManagerDSM.setCurrentIndex(-1) self.layerComboManagerDEM = QgsMapLayerComboBox(self.dlg.widgetDEM) self.layerComboManagerDEM.setFilters(QgsMapLayerProxyModel.RasterLayer) self.layerComboManagerDEM.setFixedWidth(175) self.layerComboManagerDEM.setCurrentIndex(-1) self.layerComboManagerBuild = QgsMapLayerComboBox(self.dlg.widgetBuild) self.layerComboManagerBuild.setFilters(QgsMapLayerProxyModel.RasterLayer) self.layerComboManagerBuild.setFixedWidth(175) self.layerComboManagerBuild.setCurrentIndex(-1) self.layerComboManagerCDSM = QgsMapLayerComboBox(self.dlg.widgetCDSM) self.layerComboManagerCDSM.setFilters(QgsMapLayerProxyModel.RasterLayer) self.layerComboManagerCDSM.setFixedWidth(175) self.layerComboManagerCDSM.setCurrentIndex(-1) self.layerComboManagerTDSM = QgsMapLayerComboBox(self.dlg.widgetTDSM) self.layerComboManagerTDSM.setFilters(QgsMapLayerProxyModel.RasterLayer) self.layerComboManagerTDSM.setFixedWidth(175) self.layerComboManagerTDSM.setCurrentIndex(-1) # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('TreeGenerator', message) def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): # Create the dialog (after translation) and keep reference self.dlg = TreeGeneratorDialog() icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/TreeGenerator/icon.png' self.add_action( icon_path, text=self.tr(u''), callback=self.run, parent=self.iface.mainWindow()) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu( self.tr(u'&Tree Generator'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar def run(self): """Run method that performs all the real work""" # show the dialog self.dlg.show() # Run the dialog event loop self.dlg.exec_() gdal.UseExceptions() gdal.AllRegister() def folder_path(self): self.fileDialog.open() result = self.fileDialog.exec_() if result == 1: self.folderPath = self.fileDialog.selectedFiles() self.dlg.textOutput.setText(self.folderPath[0]) def start_progress(self): self.steps = 0 point = self.layerComboManagerPoint.currentLayer() if point is None: QMessageBox.critical(self.dlg, "Error", "No valid Point layer is selected") return if self.dlg.checkBoxOnlyBuilding.isChecked(): # Only building heights build = self.layerComboManagerBuild.currentLayer() dsm = None dem = None if build is None: QMessageBox.critical(self.dlg, "Error", "No valid building raster layer is selected") return provider = build.dataProvider() filePath_build = str(provider.dataSourceUri()) dataset = gdal.Open(filePath_build) build_array = dataset.ReadAsArray().astype(np.float) else: # Both building ground heights dsm = self.layerComboManagerDSM.currentLayer() dem = self.layerComboManagerDEM.currentLayer() build = None if dsm is None: QMessageBox.critical(self.dlg, "Error", "No valid ground and building DSM raster layer is selected") return if dem is None: QMessageBox.critical(self.dlg, "Error", "No valid ground DEM raster layer is selected") return provider = dsm.dataProvider() filePath_dsm = str(provider.dataSourceUri()) provider = dem.dataProvider() filePath_dem = str(provider.dataSourceUri()) dataset = gdal.Open(filePath_dsm) dsm_array = dataset.ReadAsArray().astype(np.float) dataset2 = gdal.Open(filePath_dem) dem_array = dataset2.ReadAsArray().astype(np.float) if not (dsm_array.shape[0] == dem_array.shape[0]) & (dsm_array.shape[1] == dem_array.shape[1]): QMessageBox.critical(self.dlg, "Error", "All grids must be of same pixel resolution") return build_array = dsm_array - dem_array build_array[build_array < 2.] = 1. build_array[build_array >= 2.] = 0. sizey = build_array.shape[0] sizex = build_array.shape[1] if self.dlg.checkBoxMergeCDSM.isChecked(): # vegetation cdsm cdsm = self.layerComboManagerCDSM.currentLayer() if cdsm is None: QMessageBox.critical(self.dlg, "Error", "No valid vegetation CDSM raster layer is selected") return provider = cdsm.dataProvider() filePath_cdsm = str(provider.dataSourceUri()) dataset = gdal.Open(filePath_cdsm) cdsm_array = dataset.ReadAsArray().astype(np.float) tdsm = self.layerComboManagerCDSM.currentLayer() if tdsm is None: QMessageBox.critical(self.dlg, "Error", "No valid vegetation TDSM raster layer is selected") return provider = tdsm.dataProvider() filePath_tdsm = str(provider.dataSourceUri()) dataset = gdal.Open(filePath_tdsm) tdsm_array = dataset.ReadAsArray().astype(np.float) else: cdsm_array = np.zeros((sizey, sizex)) tdsm_array = np.zeros((sizey, sizex)) geotransform = dataset.GetGeoTransform() scale = 1 / geotransform[1] # nd = dataset.GetRasterBand(1).GetNoDataValue() # dem_array = np.zeros((sizex, sizey)) # Get attributes vlayer = QgsVectorLayer(point.source(), "point", "ogr") # prov = vlayer.dataProvider() # fields = prov.fields() ttype_field = self.layerComboManagerTreeTypeField.currentField() trunk_field = self.layerComboManagerTrunkHeightField.currentField() tot_field = self.layerComboManagerTotalHeightField.currentField() dia_field = self.layerComboManagerDiameterField.currentField() # idx_ttype = vlayer.fieldNameIndex(ttype_field) # idx_trunk = vlayer.fieldNameIndex(trunk_field) # idx_tot = vlayer.fieldNameIndex(tot_field) # idx_dia = vlayer.fieldNameIndex(dia_field) idx_ttype = vlayer.fields().indexFromName(ttype_field) idx_trunk = vlayer.fields().indexFromName(trunk_field) idx_tot = vlayer.fields().indexFromName(tot_field) idx_dia = vlayer.fields().indexFromName(dia_field) if self.folderPath == 'None': QMessageBox.critical(self.dlg, "Error", "Select a valid output folder") return numfeat = vlayer.featureCount() width = dataset.RasterXSize height = dataset.RasterYSize minx = geotransform[0] miny = geotransform[3] + width * geotransform[4] + height * geotransform[5] rows = build_array.shape[0] cols = build_array.shape[1] self.dlg.progressBar.setRange(0, numfeat) index = 0 # Main loop for f in vlayer.getFeatures(): # looping through each grid polygon # self.dlg.progressBar.setValue(0) index = index + 1 self.dlg.progressBar.setValue(index) attributes = f.attributes() geometry = f.geometry() feature = QgsFeature() feature.setAttributes(attributes) feature.setGeometry(geometry) y = f.geometry().centroid().asPoint().y() x = f.geometry().centroid().asPoint().x() ttype = f.attributes()[idx_ttype] trunk = f.attributes()[idx_trunk] height = f.attributes()[idx_tot] dia = f.attributes()[idx_dia] cola = np.round((x - minx) * scale) rowa = np.round((miny + rows / scale - y) * scale) # QMessageBox.information(None, "scale=", str(scale)) # QMessageBox.information(None, "x=", str(x)) # QMessageBox.information(None, "y=", str(y)) # QMessageBox.information(None, "minx=", str(minx)) # QMessageBox.information(None, "miny=", str(miny)) # QMessageBox.information(None, "cola=", str(cola)) # QMessageBox.information(None, "rowa=", str(rowa)) # QMessageBox.information(None, "rows=", str(rows)) cdsm_array, tdsm_array = makevegdems.vegunitsgeneration(build_array, cdsm_array, tdsm_array, ttype, height, trunk, dia, rowa, cola, sizex, sizey, scale) # temporary fix for mac, ISSUE #15 pf = sys.platform if pf == 'darwin' or pf == 'linux2': if not os.path.exists(self.folderPath[0]): os.makedirs(self.folderPath[0]) self.saveraster(dataset, self.folderPath[0] + '/cdsm.tif', cdsm_array) self.saveraster(dataset, self.folderPath[0] + '/tdsm.tif', tdsm_array) QMessageBox.information(self.dlg, "TreeGenerator", "Vegetation DSMs succesfully generated") def help(self): url = "https://umep-docs.readthedocs.io/en/latest/pre-processor/Spatial%20Data%20Tree%20Generator.html" webbrowser.open_new_tab(url) def saveraster(self, gdal_data, filename, raster): rows = gdal_data.RasterYSize cols = gdal_data.RasterXSize outDs = gdal.GetDriverByName("GTiff").Create(filename, cols, rows, int(1), GDT_Float32) outBand = outDs.GetRasterBand(1) # write the data outBand.WriteArray(raster, 0, 0) # flush data to disk, set the NoData value and calculate stats outBand.FlushCache() # outBand.SetNoDataValue(-9999) # georeference the image and set the projection outDs.SetGeoTransform(gdal_data.GetGeoTransform()) outDs.SetProjection(gdal_data.GetProjection())
def upload_data(self): if self.check_login(): if self.local_data_sources.count() == 0: return if self.db_connections.count() == 0: QMessageBox.warning(self, self.tr("No database available"), self.tr("Please create a database in the 'Account' tab.")) return if not self.ui.cbUploadDatabase.currentIndex() >= 0: QMessageBox.warning(self, self.tr("No database selected"), self.tr("Please select a database to upload data.")) return db_name = self.ui.cbUploadDatabase.currentText() if not self.db_connections.isPortOpen(db_name): uri = self.db_connections.cloud_layer_uri(db_name, "", "") host = str(uri.host()) port = uri.port() QMessageBox.critical(self, self.tr("Network Error"), self.tr("Could not connect to database server ({0}) on port {1}. Please contact your system administrator or internet provider to open port {1} in the firewall".format(host, port))) return # disable update of local data sources during upload, as there are # temporary layers added and removed self.do_update_local_data_sources = False self.statusBar().showMessage(self.tr("Uploading data...")) self.setCursor(Qt.WaitCursor) self.ui.btnUploadData.hide() self.ui.spinner.start() self.ui.progressWidget.show() # Map<data_source, {schema: schema, table: table, layers: layers}> data_sources_items = {} for row in range(0, self.ui.tblLocalLayers.rowCount()): data_source = unicode( self.ui.tblLocalLayers.item( row, self.COLUMN_DATA_SOURCE).text()) layers = self.local_data_sources.layers(data_source) if layers is not None: schema_name = unicode( self.ui.tblLocalLayers.cellWidget( row, self.COLUMN_SCHEMA_NAME).currentText()) table_name = unicode( self.ui.tblLocalLayers.item( row, self.COLUMN_TABLE_NAME).text()) data_sources_items[data_source] = { u'schema': unicode(schema_name), u'table': unicode(table_name), u'layers': layers} login_info = self.api.check_login(version_info=self._version_info()) try: self.maxSize = login_info['max_storage'] self.maxDBs = login_info['max_dbs'] except: self.maxSize = 50 self.maxDBs = 5 try: self.data_upload.upload(self.db_connections.db(unicode(db_name)), data_sources_items, unicode(self.maxSize)) upload_ok = True except Exception as e: ErrorReportDialog(self.tr("Upload errors occurred"), self.tr("Upload errors occurred. Not all data could be uploaded."), str(e) + "\n" + traceback.format_exc(), self.user, self).exec_() upload_ok = False self.ui.spinner.stop() self.ui.progressWidget.hide() self.ui.btnUploadData.show() self.unsetCursor() self.statusBar().showMessage("") # Refresh local layers self.do_update_local_data_sources = True self.update_local_layers() # Refresh used space after upload self.db_size(self.db_connections) if upload_ok: # Show save project dialog save_dialog = QDialog(self) save_dialog.setWindowTitle(self.tr("Save Project")) save_dialog.setLayout(QVBoxLayout()) header = QWidget() header.setLayout(QVBoxLayout()) label = QLabel(self.tr("Upload complete. The local layers in the project were replaced with the layers uploaded to the qgiscloud database.")) label.setWordWrap(True) header.layout().addWidget(label) label = QLabel(self.tr("Choose were to save the modified project:")) label.setWordWrap(True) header.layout().addWidget(label) save_dialog.layout().setContentsMargins(0, 0, 0, 0) save_dialog.layout().addWidget(header) initialPath = QgsProject.instance().fileName() if not initialPath: initialPath = QSettings().value("/UI/lastProjectDir", ".") fd = QFileDialog(None, self.tr("Save Project"), initialPath, "%s (*.qgz *.qgs)" % self.tr("QGIS Project Files")) fd.setParent(save_dialog, Qt.Widget) fd.setOption(QFileDialog.DontUseNativeDialog) fd.setAcceptMode(QFileDialog.AcceptSave) save_dialog.layout().addWidget(fd) header.layout().setContentsMargins(fd.layout().contentsMargins()) fd.accepted.connect(save_dialog.accept) fd.rejected.connect(save_dialog.reject) if save_dialog.exec_() == QDialog.Accepted: files = list(fd.selectedFiles()) if files: QgsProject.instance().setFileName(files[0]) self.iface.actionSaveProject().trigger() # Switch to map tab self.ui.tabWidget.setCurrentWidget(self.ui.mapTab)
class PotentialSlopeFailure(object): """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'PotentialSlopeFailure_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) self.dlg = PotentialSlopeFailureDialog(self.iface) self.dlg.runButton.clicked.connect(self.start_progress) self.dlg.pushButtonHelp.clicked.connect(self.help) self.dlg.pushButtonSave.clicked.connect(self.folder_path) self.fileDialog = QFileDialog() self.fileDialog.setFileMode(QFileDialog.Directory) self.fileDialog.setOption(QFileDialog.ShowDirsOnly, True) # Declare instance attributes #self.actions = [] #self.menu = self.tr(u'&Potential Slope Failure') # TODO: We are going to let the user set this up in a future iteration #self.toolbar = self.iface.addToolBar(u'PotentialSlopeFailure') #self.toolbar.setObjectName(u'PotentialSlopeFailure') # self.layerComboManagerDEM = RasterLayerCombo(self.dlg.comboBoxDem) # RasterLayerCombo(self.dlg.comboBoxDem, initLayer="") # self.layerComboManagerSOIL = RasterLayerCombo(self.dlg.comboBoxSoil) # RasterLayerCombo(self.dlg.comboBoxSoil, initLayer="") self.layerComboManagerDEM = QgsMapLayerComboBox(self.dlg.widgetDEM) self.layerComboManagerDEM.setFilters(QgsMapLayerProxyModel.RasterLayer) self.layerComboManagerDEM.setFixedWidth(175) self.layerComboManagerSOIL = QgsMapLayerComboBox(self.dlg.widgetSOIL) self.layerComboManagerSOIL.setFilters( QgsMapLayerProxyModel.RasterLayer) self.layerComboManagerSOIL.setFixedWidth(175) self.folderPath = 'None' # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('PotentialSlopeFailure', message) # def add_action( # self, # icon_path, # text, # callback, # enabled_flag=True, # add_to_menu=True, # add_to_toolbar=True, # status_tip=None, # whats_this=None, # parent=None): # """Add a toolbar icon to the toolbar. # # :param icon_path: Path to the icon for this action. Can be a resource # path (e.g. ':/plugins/foo/bar.png') or a normal file system path. # :type icon_path: str # # :param text: Text that should be shown in menu items for this action. # :type text: str # # :param callback: Function to be called when the action is triggered. # :type callback: function # # :param enabled_flag: A flag indicating if the action should be enabled # by default. Defaults to True. # :type enabled_flag: bool # # :param add_to_menu: Flag indicating whether the action should also # be added to the menu. Defaults to True. # :type add_to_menu: bool # # :param add_to_toolbar: Flag indicating whether the action should also # be added to the toolbar. Defaults to True. # :type add_to_toolbar: bool # # :param status_tip: Optional text to show in a popup when mouse pointer # hovers over the action. # :type status_tip: str # # :param parent: Parent widget for the new action. Defaults None. # :type parent: QWidget # # :param whats_this: Optional text to show in the status bar when the # mouse pointer hovers over the action. # # :returns: The action that was created. Note that the action is also # added to self.actions list. # :rtype: QAction # """ # # # Create the dialog (after translation) and keep reference # # self.dlg = PotentialSlopeFailureDialog() # # icon = QIcon(icon_path) # action = QAction(icon, text, parent) # action.triggered.connect(callback) # action.setEnabled(enabled_flag) # # if status_tip is not None: # action.setStatusTip(status_tip) # # if whats_this is not None: # action.setWhatsThis(whats_this) # # if add_to_toolbar: # self.toolbar.addAction(action) # # if add_to_menu: # self.iface.addPluginToMenu(self.menu, action) # # self.actions.append(action) # # return action def initGui(self): # Create action that will start plugin configuration self.action = QAction( QIcon(':/plugins/PotentialSlopeFailure/slopeicon.png'), 'Calculates areas prone to slope failures in cohesive soils', self.iface.mainWindow()) # connect the action to the run method self.action.triggered.connect(self.run) # Add toolbar button and menu item self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu(self.tr("&Potential Slope Failure"), self.action) #"""Create the menu entries and toolbar icons inside the QGIS GUI.""" # #icon_path = ':/plugins/PotentialSlopeFailure/icon.png' #self.add_action( # icon_path, # text=self.tr(u'Calculates areas prone to slope failures in cohesive soils'), # callback=self.run, # parent=self.iface.mainWindow()) def unload(self): # Remove the plugin menu item and icon self.iface.removePluginMenu("&Potential Slope Failure", self.action) self.iface.removeToolBarIcon(self.action) # """Removes the plugin menu item and icon from QGIS GUI.""" # for action in self.actions: self.iface.removePluginMenu( # self.tr(u'&Potential Slope Failure'), # action) # self.iface.removeToolBarIcon(action) # remove the toolbar # del self.toolbar def run(self): self.dlg.show() self.dlg.exec_() def folder_path(self): self.fileDialog.open() result = self.fileDialog.exec_() if result == 1: self.folderPath = self.fileDialog.selectedFiles() self.dlg.textOutput.setText(self.folderPath[0]) def start_progress(self): if self.folderPath == 'None': QMessageBox.critical(None, "Error", "Select a valid output folder") return # Load DEM demlayer = self.layerComboManagerDEM.currentLayer() if demlayer is None: QMessageBox.critical(None, "Error", "No valid DEM raster layer is selected") return provider = demlayer.dataProvider() filepath_dem = str(provider.dataSourceUri()) gdal_dem = gdal.Open(filepath_dem) dem = gdal_dem.ReadAsArray().astype(np.float) sizex = dem.shape[0] sizey = dem.shape[1] geotransform = gdal_dem.GetGeoTransform() scale = 1 / geotransform[1] # Load Soil soillayer = self.layerComboManagerSOIL.currentLayer() if soillayer is None: QMessageBox.critical(None, "Error", "No valid Soil raster selected") return # load raster gdal.AllRegister() provider = soillayer.dataProvider() filePathOld = str(provider.dataSourceUri()) dataSet = gdal.Open(filePathOld) soil = dataSet.ReadAsArray().astype(np.float) soilsizex = soil.shape[0] soilsizey = soil.shape[1] if not (soilsizex == sizex) & (soilsizey == sizey): QMessageBox.critical( None, "Error", "The grids must be of same extent and resolution") return itera = int(360 / self.dlg.spinBoxIter.value()) alt = self.dlg.spinBoxAlt.value() shtot = np.zeros((sizex, sizey)) index = 0 # Inverting dem dem = dem * (-1.) + np.max(dem) self.dlg.progressBar.setRange(0, self.dlg.spinBoxIter.value()) for i in range(0, self.dlg.spinBoxIter.value()): azi = itera * i self.dlg.progressBar.setValue(i + 1) # self.iface.messageBar().pushMessage("ShadowGenerator", str(azi)) sh = shadow.shadowingfunctionglobalradiation( dem, azi, alt, scale, self.dlg, 1) shtot = shtot + sh index += 1 zon1 = shtot / index zon1[zon1 == 1] = 2 zon1[zon1 < 1] = 1 karta1a = zon1 * soil karta1a[karta1a == 0] = 3 filename = self.folderPath[0] + '/map1a.tif' self.saveraster(gdal_dem, filename, karta1a) # load result into canvas if self.dlg.checkBoxIntoCanvas.isChecked(): rlayer = self.iface.addRasterLayer(filename) # Trigger a repaint if hasattr(rlayer, "setCacheImage"): rlayer.setCacheImage(None) rlayer.triggerRepaint() rlayer.loadNamedStyle(self.plugin_dir + '/misc/map1a.qml') if hasattr(rlayer, "setCacheImage"): rlayer.setCacheImage(None) rlayer.triggerRepaint() self.dlg.progressBar.setValue(0) QMessageBox.information( self.dlg, "Calculation done!", "Output (map1a.tif) created in: " + self.folderPath[0] + "/") def help(self): url = "https://github.com/biglimp/PotentialSlopeFailure/wiki/Potential-Slope-Failure-plugin-for-QGIS" webbrowser.open_new_tab(url) def saveraster(self, gdal_data, filename, raster): rows = gdal_data.RasterYSize cols = gdal_data.RasterXSize outDs = gdal.GetDriverByName("GTiff").Create(filename, cols, rows, int(1), GDT_Float32) outBand = outDs.GetRasterBand(1) # write the data outBand.WriteArray(raster, 0, 0) # flush data to disk, set the NoData value and calculate stats outBand.FlushCache() outBand.SetNoDataValue(-9999) # georeference the image and set the projection outDs.SetGeoTransform(gdal_data.GetGeoTransform()) outDs.SetProjection(gdal_data.GetProjection())