def processAlgorithm(self, parameters, context, feedback): zs = QgsZonalStatistics( self.vectorLayer, self.raster_interface, self.raster_crs, self.raster_units_per_pixel_x, self.raster_units_per_pixel_y, self.columnPrefix, self.bandNumber, QgsZonalStatistics.Statistics(self.selectedStats)) zs.calculateStatistics(feedback) return {self.INPUT_VECTOR: self.vectorLayer}
def processAlgorithm(self, parameters, context, feedback): zs = QgsZonalStatistics(self.vectorLayer, self.rasterLayer, self.columnPrefix, self.bandNumber, QgsZonalStatistics.Statistics(self.selectedStats)) zs.calculateStatistics(feedback) return {self.INPUT_VECTOR: self.vectorLayer}
def zonalStat(self, vlayer, rlayer_source): prefix = 'Erosion_G_' zonalstats = QgsZonalStatistics(vlayer, rlayer_source, prefix, stats=QgsZonalStatistics.Statistic(4)) zonalstats.calculateStatistics(None) vlayer.startEditing() for field in vlayer.pendingFields(): if field.name() == 'Erosion_G_': idx = vlayer.fieldNameIndex(field.name()) vlayer.renameAttribute(idx, 'G') vlayer.commitChanges()
def processAlgorithm(self, parameters, context, feedback): for b in range(self.raster_band_count): if feedback.isCanceled(): break columnPrefix = '{}b{}_'.format(self.columnPrefix, b + 1) zs = QgsZonalStatistics( self.vectorLayer, self.raster_interface, self.raster_crs, self.raster_units_per_pixel_x, self.raster_units_per_pixel_y, columnPrefix, b + 1, QgsZonalStatistics.Statistics(self.selectedStats)) zs.calculateStatistics(feedback) return {self.INPUT_VECTOR: self.vectorLayer}
def _calculate_means(self, polyg_layer_files, raster_layer_files, attribute_names): # polygon_layer_files: list of absolute path polygon layer files # raster_layer_files: list of absolute path raster layer files # attribute_names: name prefix of newly calculated attributes (means from raster to polygon) for poly in polyg_layer_files: for rast, attr_name in zip(raster_layer_files, attribute_names): assert os.path.isfile(poly), "File {} does not exist.".format( poly) assert os.path.isfile(rast), "File {} does not exist.".format( rast) poly_object = QgsVectorLayer(poly, 'zonepolygons', 'ogr') zoneStat = QgsZonalStatistics(poly_object, rast, attr_name, 1, QgsZonalStatistics.Mean) check = zoneStat.calculateStatistics(None) assert check == 0, "zoneStat.calculateStatistics(None) returned non-zero value... check input layers!"
def processAlgorithm(self, feedback): rasterPath = self.getParameterValue(self.INPUT_RASTER) vectorPath = self.getParameterValue(self.INPUT_VECTOR) bandNumber = self.getParameterValue(self.RASTER_BAND) columnPrefix = self.getParameterValue(self.COLUMN_PREFIX) st = self.getParameterValue(self.STATISTICS) vectorLayer = dataobjects.getObjectFromUri(vectorPath) keys = list(self.STATS.keys()) selectedStats = 0 for i in st: selectedStats |= self.STATS[keys[i]] zs = QgsZonalStatistics(vectorLayer, rasterPath, columnPrefix, bandNumber, selectedStats) zs.calculateStatistics(None) self.setOutputValue(self.OUTPUT_LAYER, vectorPath)
def get_z_max_z_min(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) points = getPointsFromRectangleParams(self.rect_Params) # Specify the geometry type layer = QgsVectorLayer('Polygon?crs=' + self.map_crs.authid(), 'polygon', 'memory') # Set the provider to accept the data source prov = layer.dataProvider() geom = [[ QgsPointXY(points[0][0], points[0][1]), QgsPointXY(points[1][0], points[1][1]), QgsPointXY(points[2][0], points[2][1]), QgsPointXY(points[3][0], points[3][1]) ]] # Add a new feature and assign the geometry feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPolygonXY(geom)) prov.addFeatures([feat]) # Update extent of the layer layer.updateExtents() zoneStat = QgsZonalStatistics( layer, self.layer, "", 1, QgsZonalStatistics.Max | QgsZonalStatistics.Min) zoneStat.calculateStatistics(None) minVal = 0 maxVal = 0 stats = layer.getFeature(1).attributes() if (len(stats) > 0): if stats[0] is not None: minVal = stats[0] if stats[1] is not None: maxVal = stats[1] self.z_max = round(maxVal, 3) self.z_min = round(minVal, 3) self.ui.ZMaxLabel.setText(str(self.z_max) + ' m') self.ui.ZMinLabel.setText(str(self.z_min) + ' m') layer = None QApplication.restoreOverrideCursor()
def processAlgorithm(self, progress): rasterPath = self.getParameterValue(self.INPUT_RASTER) vectorPath = self.getParameterValue(self.INPUT_VECTOR) bandNumber = self.getParameterValue(self.RASTER_BAND) columnPrefix = self.getParameterValue(self.COLUMN_PREFIX) st = self.getParameterValue(self.STATISTICS) vectorLayer = dataobjects.getObjectFromUri(vectorPath) keys = list(self.STATS.keys()) selectedStats = 0 for i in st: selectedStats |= self.STATS[keys[i]] zs = QgsZonalStatistics(vectorLayer, rasterPath, columnPrefix, bandNumber, selectedStats) zs.calculateStatistics(None) self.setOutputValue(self.OUTPUT_LAYER, vectorPath)
def testStatistics(self): """Test zonal stats""" sep = os.sep TEST_DATA_DIR = unitTestDataPath() + sep + "zonalstatistics" + sep myTempPath = QDir.tempPath() + sep testDir = QDir(TEST_DATA_DIR) for f in testDir.entryList(QDir.Files): QFile.remove(myTempPath + f) QFile.copy(TEST_DATA_DIR + f, myTempPath + f) myVector = QgsVectorLayer(myTempPath + "polys.shp", "poly", "ogr") myRasterPath = myTempPath + "edge_problem.asc" zs = QgsZonalStatistics(myVector, myRasterPath, "", 1) zs.calculateStatistics(None) feat = QgsFeature() # validate statistics for each feature request = QgsFeatureRequest().setFilterFid(0) feat = myVector.getFeatures(request).next() myMessage = ('Expected: %f\nGot: %f\n' % (12.0, feat[1])) assert feat[1] == 12.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (8.0, feat[2])) assert feat[2] == 8.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.666666666666667, feat[3])) assert abs(feat[3] - 0.666666666666667) < 0.00001, myMessage request.setFilterFid(1) feat = myVector.getFeatures(request).next() myMessage = ('Expected: %f\nGot: %f\n' % (9.0, feat[1])) assert feat[1] == 9.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.555555555555556, feat[3])) assert abs(feat[3] - 0.555555555555556) < 0.00001, myMessage request.setFilterFid(2) feat = myVector.getFeatures(request).next() myMessage = ('Expected: %f\nGot: %f\n' % (6.0, feat[1])) assert feat[1] == 6.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.833333333333333, feat[3])) assert abs(feat[3] - 0.833333333333333) < 0.00001, myMessage
def calculate_raster_stats(loss_layer, zonal_layer, iface): """ In case the layer containing loss data is raster, use QgsZonalStatistics to calculate NUM_POINTS, SUM and AVG values for each zone """ zonal_statistics = QgsZonalStatistics( zonal_layer, loss_layer.dataProvider().dataSourceUri()) progress_dialog = QProgressDialog(tr('Calculating zonal statistics'), tr('Abort...'), 0, 0) zonal_statistics.calculateStatistics(progress_dialog) # TODO: This is not giving any warning in case no loss points are # contained by any of the zones if progress_dialog.wasCanceled(): msg = ("You aborted aggregation, so there are" " no data for analysis. Exiting...") log_msg(msg, level='C', message_bar=iface.messageBar()) # FIXME: We probably need to return something more return (loss_layer, zonal_layer)
def processAlgorithm(self, parameters, context, feedback): bandNumber = self.parameterAsInt(parameters, self.RASTER_BAND, context) columnPrefix = self.parameterAsString(parameters, self.COLUMN_PREFIX, context) st = self.parameterAsEnums(parameters, self.STATISTICS, context) vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT_VECTOR, context) rasterLayer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context) keys = list(self.STATS.keys()) selectedStats = 0 for i in st: selectedStats |= self.STATS[keys[i]] zs = QgsZonalStatistics(vectorLayer, rasterLayer, columnPrefix, bandNumber, selectedStats) zs.calculateStatistics(feedback) return {self.INPUT_VECTOR: vectorLayer}
def processAlgorithm(self, context, feedback): rasterPath = self.getParameterValue(self.INPUT_RASTER) vectorPath = self.getParameterValue(self.INPUT_VECTOR) bandNumber = self.getParameterValue(self.RASTER_BAND) columnPrefix = self.getParameterValue(self.COLUMN_PREFIX) st = self.getParameterValue(self.STATISTICS) vectorLayer = QgsProcessingUtils.mapLayerFromString( vectorPath, context) rasterLayer = QgsProcessingUtils.mapLayerFromString( rasterPath, context) keys = list(self.STATS.keys()) selectedStats = 0 for i in st: selectedStats |= self.STATS[keys[i]] zs = QgsZonalStatistics(vectorLayer, rasterLayer, columnPrefix, bandNumber, selectedStats) zs.calculateStatistics(None) self.setOutputValue(self.OUTPUT_LAYER, vectorPath)
def zonal_stat(self, vector_file, raster_file_name, stat_type="Majority"): polygonLayer = QgsVectorLayer(vector_file, 'zonepolygons', 'ogr') zoneStat = '' if stat_type == "mean": zoneStat = QgsZonalStatistics(polygonLayer, raster_file_name, '_', 1, QgsZonalStatistics.Mean) else: zoneStat = QgsZonalStatistics(polygonLayer, raster_file_name, '_', 1, QgsZonalStatistics.Majority) zoneStat.calculateStatistics(None)
def test_enum_conversion(self): """Test regression GH #43245""" tmp = QTemporaryDir() origin = os.path.join(TEST_DATA_DIR, 'raster', 'band1_byte_ct_epsg4326.tif') dest = os.path.join(tmp.path(), 'band1_byte_ct_epsg4326.tif') shutil.copyfile(origin, dest) layer = QgsRasterLayer(dest, 'rast', 'gdal') stats = QgsZonalStatistics.calculateStatistics( layer.dataProvider(), QgsGeometry.fromWkt(layer.extent().asWktPolygon()), layer.rasterUnitsPerPixelX(), layer.rasterUnitsPerPixelY(), 1, QgsZonalStatistics.Statistic.Max | QgsZonalStatistics.Statistic.Median) self.assertEqual(sorted(list(stats.keys())), [ QgsZonalStatistics.Statistic.Median, QgsZonalStatistics.Statistic.Max ]) self.assertEqual(stats[QgsZonalStatistics.Statistic.Median], 142.0) self.assertEqual(stats[QgsZonalStatistics.Statistic.Max], 254.0)
def _aggregateRasterImpact(self, theQGISImpactLayer): """ Performs Aggregation postprocessing step on raster impact layers by calling QgsZonalStatistics Args: QgsMapLayer: theQGISImpactLayer a valid QgsVectorLayer Returns: None """ myZonalStatistics = QgsZonalStatistics( self.layer, theQGISImpactLayer.dataProvider().dataSourceUri(), self.prefix) myProgressDialog = QtGui.QProgressDialog( self.tr('Calculating zonal statistics'), self.tr('Abort...'), 0, 0) startTime = time.clock() myZonalStatistics.calculateStatistics(myProgressDialog) if myProgressDialog.wasCanceled(): QtGui.QMessageBox.error( self, self.tr('ZonalStats: Error'), self.tr('You aborted aggregation, ' 'so there are no data for analysis. Exiting...')) cppDuration = time.clock() - startTime print 'CPP duration: %ss' % (cppDuration) startTime = time.clock() # new way # myZonalStatistics = { # 0L: {'count': 50539, # 'sum': 12015061.876953125, # 'mean': 237.73841739949594}, # 1L: { # 'count': 19492, # 'sum': 2945658.1220703125, # 'mean': 151.12138939412642}, # 2L: { # 'count': 57372, # 'sum': 1643522.3984985352, 'mean': 28.6467684323108}, # 3L: { # 'count': 0.00013265823369700314, # 'sum': 0.24983273179242008, # 'mean': 1883.2810058593748}, # 4L: { # 'count': 1.8158245316933218e-05, # 'sum': 0.034197078505115275, # 'mean': 1883.281005859375}, # 5L: { # 'count': 73941, # 'sum': 10945062.435424805, # 'mean': 148.024268476553}, # 6L: { # 'count': 54998, # 'sum': 11330910.488220215, # 'mean': 206.02404611477172}} myZonalStatistics = calculateZonalStats(theQGISImpactLayer, self.layer) pyDuration = time.clock() - startTime print 'CPP duration: %ss' % (pyDuration) try: ratio = pyDuration / cppDuration except ZeroDivisionError: ratio = 1 print 'py to CPP: %s%%' % (ratio * 100) # FIXME (MB) remove this once fully implemented oldPrefix = self.prefix self.prefix = 'newAggr' myProvider = self.layer.dataProvider() self.layer.startEditing() # add fields for stats to aggregation layer # { 1: {'sum': 10, 'count': 20, 'min': 1, 'max': 4, 'mean': 2}, # QgsField(self._minFieldName(), QtCore.QVariant.Double), # QgsField(self._maxFieldName(), QtCore.QVariant.Double)] myFields = [QgsField(self._countFieldName(), QtCore.QVariant.Double), QgsField(self._sumFieldName(), QtCore.QVariant.Double), QgsField(self._meanFieldName(), QtCore.QVariant.Double) ] myProvider.addAttributes(myFields) self.layer.commitChanges() sumIndex = myProvider.fieldNameIndex(self._sumFieldName()) countIndex = myProvider.fieldNameIndex(self._countFieldName()) meanIndex = myProvider.fieldNameIndex(self._meanFieldName()) # minIndex = myProvider.fieldNameIndex(self._minFieldName()) # maxIndex = myProvider.fieldNameIndex(self._maxFieldName()) self.layer.startEditing() allPolygonAttrs = myProvider.attributeIndexes() myProvider.select(allPolygonAttrs) myFeature = QgsFeature() while myProvider.nextFeature(myFeature): myFid = myFeature.id() myStats = myZonalStatistics[myFid] # minIndex: QtCore.QVariant(myStats['min']), # maxIndex: QtCore.QVariant(myStats['max'])} attrs = {sumIndex: QtCore.QVariant(myStats['sum']), countIndex: QtCore.QVariant(myStats['count']), meanIndex: QtCore.QVariant(myStats['mean']) } myProvider.changeAttributeValues({myFid: attrs}) self.layer.commitChanges() # FIXME (MB) remove this once fully implemented self.prefix = oldPrefix return
#Name of the CSV file that will be output out_csv = "/Users/azharhussain/Dropbox/GCP_Reanalysis/RA_Files/Azhar/Nightlights/Income/Data/NL/{}_{}_{}{}_NL_new.csv".format( input, x, transform, z + 1) vbaselayer = QgsVectorLayer(shapefile, "adm2", "ogr") #Reproject the SHP into robinson CRS (so that the area is constant within pixels) QgsVectorFileWriter.writeAsVectorFormat( vbaselayer, "{}.shp".format(temp_name), "utf-8", QgsCoordinateReferenceSystem(4326), "ESRI Shapefile") vlayer = QgsVectorLayer("{}.shp".format(temp_name), "projected", "ogr") QgsMapLayerRegistry.instance().addMapLayer(vlayer) #ZS calculation zoneStat = QgsZonalStatistics(vlayer, outFile, 'nl_', 1) zoneStat.calculateStatistics(None) #Export csv QgsVectorFileWriter.writeAsVectorFormat( vlayer, "{}".format(out_csv), "utf-8", None, "CSV", layerOptions='GEOMETRY=AS_WKT') QgsMapLayerRegistry.instance().removeMapLayer(vlayer.id()) #Remove the temporary files for var in ['cpg', 'dbf', 'prj', 'qpj', 'shx', 'shp']: os.remove("{}.{}".format(temp_name, var))
from qgis.utils import iface from PyQt4.QtCore import * from qgis.analysis import QgsZonalStatistics import time layers = iface.legendInterface().layers() polygonLayer = layers[0] count = 1 for layer in layers[1:]: print(layer.name()) zoneStat = QgsZonalStatistics( polygonLayer, layer.source(), str(count) + "_", 1, QgsZonalStatistics.Count | QgsZonalStatistics.Mean | QgsZonalStatistics.Median | QgsZonalStatistics.StDev | QgsZonalStatistics.Min | QgsZonalStatistics.Max) zoneStat.calculateStatistics(None) time.sleep(180) count += 1
## Create Plot Shapefiles for plot_buffer_size in plot_buffers: study_area_shape_path = os.path.join( output_directory, "StudyArea_" + str(plot_buffer_size) + "m.shp") buffered_vector = create_study_area_shapefile(plot_list_path, plot_buffer_size, study_area_shape_path) buffered_studyareas[plot_buffer_size] = study_area_shape_path for predictor_resolution, all_predictors_per_resolution in predictors.iteritems( ): for predictor in all_predictors_per_resolution: if "RS" not in predictor_resolution: zoneStat = QgsZonalStatistics( buffered_vector, predictor.path, str(predictor_resolution + predictor.short_name), 1, QgsZonalStatistics.Mean | QgsZonalStatistics.Max | QgsZonalStatistics.Min | QgsZonalStatistics.Range | QgsZonalStatistics.StDev) zoneStat.calculateStatistics(None) else: zoneStat = QgsZonalStatistics( buffered_vector, predictor.path, str(predictor_resolution + predictor.short_name + str(predictor.band)), int(predictor.band), QgsZonalStatistics.Mean | QgsZonalStatistics.StDev) zoneStat.calculateStatistics(None) write_results_file(buffered_studyareas, output_directory) write_legend_file(predictors, output_directory)
# -*- coding: utf-8 -*- """ Created on Sun Jun 15 19:07:17 2014 Source: http://gis.stackexchange.com/questions/45284/how-to-use-qgis-zonal-stats-plugin-from-python-console @author: jobel """ from qgis.analysis import QgsZonalStatistics #specify polygon shapefile vector polygonLayer = QgsVectorLayer('F:/temp/zonalstat/zonePoly.shp', 'zonepolygons', "ogr") # specify raster filename rasterFilePath = 'F:/temp/zonalstat/raster1.tif' # usage - QgsZonalStatistics (QgsVectorLayer *polygonLayer, const QString &rasterFile, const QString &attributePrefix="", int rasterBand=1) zoneStat = QgsZonalStatistics(polygonLayer, rasterFilePath, 'pre-', 1) zoneStat.calculateStatistics(None)
def zonal_stats(raster, vector, callback=None): """Reclassify a continuous raster layer. Issue https://github.com/inasafe/inasafe/issues/3190 :param raster: The raster layer. :type raster: QgsRasterLayer :param vector: The vector layer. :type vector: QgsVectorLayer :param callback: A function to all to indicate progress. The function should accept params 'current' (int), 'maximum' (int) and 'step' (str). Defaults to None. :type callback: function :return: The output of the zonal stats. :rtype: QgsVectorLayer .. versionadded:: 4.0 """ output_layer_name = zonal_stats_steps['output_layer_name'] processing_step = zonal_stats_steps['step_name'] layer = create_memory_layer( output_layer_name, vector.geometryType(), vector.crs(), vector.fields() ) copy_layer(vector, layer) input_band = layer.keywords.get('active_band', 1) analysis = QgsZonalStatistics( layer, raster.source(), 'exposure_', input_band, QgsZonalStatistics.Sum) result = analysis.calculateStatistics(None) LOGGER.debug(tr('Zonal stats on %s : %s' % (raster.source(), result))) layer.startEditing() exposure = raster.keywords['exposure'] output_field = exposure_count_field['field_name'] % exposure fields_to_rename = { 'exposure_sum': output_field } copy_fields(layer, fields_to_rename) remove_fields(layer, fields_to_rename.keys()) layer.commitChanges() # The zonal stats is producing some None values. We need to fill these # with 0. See issue : #3778 # We should start a new editing session as previous fields need to be # commited first. layer.startEditing() request = QgsFeatureRequest() expression = '\"%s\" is None' % output_field request.setFilterExpression(expression) request.setFlags(QgsFeatureRequest.NoGeometry) index = layer.fieldNameIndex(output_field) for feature in layer.getFeatures(): if feature[output_field] is None: layer.changeAttributeValue(feature.id(), index, 0) layer.commitChanges() layer.keywords = raster.keywords.copy() layer.keywords['inasafe_fields'] = vector.keywords['inasafe_fields'].copy() layer.keywords['inasafe_default_values'] = ( raster.keywords['inasafe_default_values'].copy()) key = exposure_count_field['key'] % raster.keywords['exposure'] # Special case here, one field is the exposure count and the total. layer.keywords['inasafe_fields'][key] = output_field layer.keywords['inasafe_fields'][total_field['key']] = output_field layer.keywords['exposure_keywords'] = raster.keywords.copy() layer.keywords['hazard_keywords'] = vector.keywords[ 'hazard_keywords'].copy() layer.keywords['aggregation_keywords'] = ( vector.keywords['aggregation_keywords']) layer.keywords['layer_purpose'] = ( layer_purpose_aggregate_hazard_impacted['key']) layer.keywords['title'] = output_layer_name check_layer(layer) return layer
def zonal_stats(raster, vector): """Reclassify a continuous raster layer. Issue https://github.com/inasafe/inasafe/issues/3190 The algorithm will take care about projections. We don't want to reproject the raster layer. So if CRS are different, we reproject the vector layer and then we do a lookup from the reprojected layer to the original vector layer. :param raster: The raster layer. :type raster: QgsRasterLayer :param vector: The vector layer. :type vector: QgsVectorLayer :return: The output of the zonal stats. :rtype: QgsVectorLayer .. versionadded:: 4.0 """ output_layer_name = zonal_stats_steps['output_layer_name'] exposure = raster.keywords['exposure'] if raster.crs().authid() != vector.crs().authid(): layer = reproject(vector, raster.crs()) # We prepare the copy output_layer = create_memory_layer( output_layer_name, vector.geometryType(), vector.crs(), vector.fields() ) copy_layer(vector, output_layer) else: layer = create_memory_layer( output_layer_name, vector.geometryType(), vector.crs(), vector.fields() ) copy_layer(vector, layer) input_band = layer.keywords.get('active_band', 1) analysis = QgsZonalStatistics( layer, raster, 'exposure_', input_band, QgsZonalStatistics.Sum) result = analysis.calculateStatistics(None) LOGGER.debug(tr('Zonal stats on %s : %s' % (raster.source(), result))) output_field = exposure_count_field['field_name'] % exposure if raster.crs().authid() != vector.crs().authid(): output_layer.startEditing() field = create_field_from_definition( exposure_count_field, exposure) output_layer.addAttribute(field) new_index = output_layer.fields().lookupField(field.name()) old_index = layer.fields().lookupField('exposure_sum') for feature_input, feature_output in zip( layer.getFeatures(), output_layer.getFeatures()): output_layer.changeAttributeValue( feature_input.id(), new_index, feature_input[old_index]) output_layer.commitChanges() layer = output_layer else: fields_to_rename = { 'exposure_sum': output_field } if qgis_version() >= 21600: rename_fields(layer, fields_to_rename) else: copy_fields(layer, fields_to_rename) remove_fields(layer, list(fields_to_rename.keys())) layer.commitChanges() # The zonal stats is producing some None values. We need to fill these # with 0. See issue : #3778 # We should start a new editing session as previous fields need to be # committed first. layer.startEditing() request = QgsFeatureRequest() expression = '\"%s\" is None' % output_field request.setFilterExpression(expression) request.setFlags(QgsFeatureRequest.NoGeometry) index = layer.fields().lookupField(output_field) for feature in layer.getFeatures(): if feature[output_field] is None: layer.changeAttributeValue(feature.id(), index, 0) layer.commitChanges() layer.keywords = raster.keywords.copy() layer.keywords['inasafe_fields'] = vector.keywords['inasafe_fields'].copy() layer.keywords['inasafe_default_values'] = ( raster.keywords['inasafe_default_values'].copy()) key = exposure_count_field['key'] % raster.keywords['exposure'] # Special case here, one field is the exposure count and the total. layer.keywords['inasafe_fields'][key] = output_field layer.keywords['inasafe_fields'][total_field['key']] = output_field layer.keywords['exposure_keywords'] = raster.keywords.copy() layer.keywords['hazard_keywords'] = vector.keywords[ 'hazard_keywords'].copy() layer.keywords['aggregation_keywords'] = ( vector.keywords['aggregation_keywords']) layer.keywords['layer_purpose'] = ( layer_purpose_aggregate_hazard_impacted['key']) layer.keywords['title'] = output_layer_name check_layer(layer) return layer
#################################################### import os, sys from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry, QgsZonalStatistics # Add polygon layer #specify polygon shapefile vector polygonLayer = QgsVectorLayer('/Users/amirsiraj/GoFlex/DataNow/Admin_units/south_America.shp', 'zonepolygons', "ogr") vtypes = ["cumI_SA_repl_", "cumPI_SA_repl_", "cumBI_SA_repl_"] sufs = ["I","PI","BI"] rplst = range(1,8,1) + range(9,101,1) rplst = range(1,8,1)+ range(9,59,1) + range(60,92,1) + range(93,101,1) rplst = range (501,1001,1) rng2 = range (1,2,1) + range(3,4,1) for vtype in rng2 : for repl in rplst : # Add raster 1 rasterFilePath = '/Users/amirsiraj/GoFlex/zika/outputbk/'+ vtypes[vtype-1] + str(repl) +'_stat.bil' zoneStat = QgsZonalStatistics (polygonLayer, rasterFilePath, sufs[vtype-1]+str(repl), 1, QgsZonalStatistics.Sum) zoneStat.calculateStatistics(None) print(vtype) print(repl)
def zonal_stats(raster, vector, callback=None): """Reclassify a continuous raster layer. Issue https://github.com/inasafe/inasafe/issues/3190 :param raster: The raster layer. :type raster: QgsRasterLayer :param vector: The vector layer. :type vector: QgsVectorLayer :param callback: A function to all to indicate progress. The function should accept params 'current' (int), 'maximum' (int) and 'step' (str). Defaults to None. :type callback: function :return: The output of the zonal stats. :rtype: QgsVectorLayer .. versionadded:: 4.0 """ output_layer_name = zonal_stats_steps['output_layer_name'] processing_step = zonal_stats_steps['step_name'] layer = create_memory_layer( output_layer_name, vector.geometryType(), vector.crs(), vector.fields() ) copy_layer(vector, layer) analysis = QgsZonalStatistics( layer, raster.source(), 'exposure_', 1, QgsZonalStatistics.Sum) result = analysis.calculateStatistics(None) LOGGER.debug(tr('Zonal stats on %s : %s' % (raster.source(), result))) layer.startEditing() exposure = raster.keywords['exposure'] output_field = exposure_count_field['field_name'] % exposure fields_to_rename = { 'exposure_sum': output_field } copy_fields(layer, fields_to_rename) remove_fields(layer, fields_to_rename.keys()) layer.commitChanges() # The zonal stats is producing some None values. We need to fill these # with 0. See issue : #3778 # We should start a new editing session as previous fields need to be # commited first. layer.startEditing() request = QgsFeatureRequest() expression = '\"%s\" is None' % output_field request.setFilterExpression(expression) request.setFlags(QgsFeatureRequest.NoGeometry) index = layer.fieldNameIndex(output_field) for feature in layer.getFeatures(): if feature[output_field] is None: layer.changeAttributeValue(feature.id(), index, 0) layer.commitChanges() layer.keywords = raster.keywords.copy() layer.keywords['inasafe_fields'] = vector.keywords['inasafe_fields'].copy() layer.keywords['inasafe_default_values'] = ( raster.keywords['inasafe_default_values'].copy()) key = exposure_count_field['key'] % raster.keywords['exposure'] # Special case here, one field is the exposure count and the total. layer.keywords['inasafe_fields'][key] = output_field layer.keywords['inasafe_fields'][total_field['key']] = output_field layer.keywords['exposure_keywords'] = raster.keywords.copy() layer.keywords['hazard_keywords'] = vector.keywords[ 'hazard_keywords'].copy() layer.keywords['aggregation_keywords'] = ( vector.keywords['aggregation_keywords']) layer.keywords['layer_purpose'] = ( layer_purpose_aggregate_hazard_impacted['key']) layer.keywords['title'] = output_layer_name check_layer(layer) return layer
import os, sys from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry, QgsZonalStatistics # Add polygon layer #specify polygon shapefile vector polygonLayer = QgsVectorLayer( '/Users/amirsiraj/GoFlex/DataNow/Admin_units/south_America.shp', 'zonepolygons', "ogr") vtypes = ["cumI_SA_repl_", "cumPI_SA_repl_", "cumBI_SA_repl_"] sufs = ["I", "PI", "BI"] rplst = range(1, 8, 1) + range(9, 101, 1) rplst = range(1, 8, 1) + range(9, 59, 1) + range(60, 92, 1) + range(93, 101, 1) rplst = range(501, 1001, 1) rng2 = range(1, 2, 1) + range(3, 4, 1) for vtype in rng2: for repl in rplst: # Add raster 1 rasterFilePath = '/Users/amirsiraj/GoFlex/zika/outputbk/' + vtypes[ vtype - 1] + str(repl) + '_stat.bil' zoneStat = QgsZonalStatistics(polygonLayer, rasterFilePath, sufs[vtype - 1] + str(repl), 1, QgsZonalStatistics.Sum) zoneStat.calculateStatistics(None) print(vtype) print(repl)
def testStatistics(self): """Test zonal stats""" TEST_DATA_DIR = unitTestDataPath() + "/zonalstatistics/" myTempPath = QDir.tempPath() + "/" testDir = QDir(TEST_DATA_DIR) for f in testDir.entryList(QDir.Files): QFile.remove(myTempPath + f) QFile.copy(TEST_DATA_DIR + f, myTempPath + f) myVector = QgsVectorLayer(myTempPath + "polys.shp", "poly", "ogr") myRaster = QgsRasterLayer(myTempPath + "edge_problem.asc", "raster", "gdal") zs = QgsZonalStatistics(myVector, myRaster, "", 1, QgsZonalStatistics.All) zs.calculateStatistics(None) feat = QgsFeature() # validate statistics for each feature request = QgsFeatureRequest().setFilterFid(0) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (12.0, feat[1])) assert feat[1] == 12.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (8.0, feat[2])) assert feat[2] == 8.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.666666666666667, feat[3])) assert abs(feat[3] - 0.666666666666667) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.47140452079103201, feat[5])) assert abs(feat[5] - 0.47140452079103201) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(1) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (9.0, feat[1])) assert feat[1] == 9.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.555555555555556, feat[3])) assert abs(feat[3] - 0.555555555555556) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.49690399499995302, feat[5])) assert abs(feat[5] - 0.49690399499995302) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(2) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (6.0, feat[1])) assert feat[1] == 6.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.833333333333333, feat[3])) assert abs(feat[3] - 0.833333333333333) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.372677996249965, feat[5])) assert abs(feat[5] - 0.372677996249965) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage
# Load the shape and raster layer_polygon = QgsVectorLayer(catchment_file, 'merit_hydro_basin', 'ogr') layer_raster = QgsRasterLayer(dem_file, 'merit_hydro_dem') # Check we loaded the layers correctly if not layer_raster.isValid(): print('Raster layer failed to load') if not layer_polygon.isValid(): print('Polygon layer failed to load') # Create a zonal statistics object, automatically saved to file band = 1 # raster band with the data we are after zonalstats = QgsZonalStatistics( layer_polygon, # shapefile layer_raster, # .tif 'elev_', # prefix for the new column added to the shapefile band, # raster band we're interested in stats=QgsZonalStatistics.Mean).calculateStatistics(None) # Clean memory qgs.exitQgis() # --- Code provenance # Generates a basic log file in the domain folder and copies the control file and itself there. # Set the log path and file name logPath = intersect_path log_suffix = '_catchment_dem_intersect_log.txt' # Create a log folder logFolder = '_workflow_log'
def start_progress(self): import datetime start = datetime.datetime.now() # Check OS and dep if sys.platform == 'darwin': gdal_os_dep = '/Library/Frameworks/GDAL.framework/Versions/Current/Programs/' else: gdal_os_dep = '' if self.dlg.canvasButton.isChecked(): # Map Canvas extentCanvasCRS = self.iface.mapCanvas() srs = extentCanvasCRS.mapSettings().destinationCrs() crs = str(srs.authid()) # old_crs = osr.SpatialReference() # old_crs.ImportFromEPSG(int(crs[5:])) can_crs = QgsCoordinateReferenceSystem(int(crs[5:])) # can_wkt = extentCanvasCRS.mapRenderer().destinationCrs().toWkt() # can_crs = osr.SpatialReference() # can_crs.ImportFromWkt(can_wkt) # Raster Layer dem_layer = self.layerComboManagerDEM.currentLayer() dem_prov = dem_layer.dataProvider() dem_path = str(dem_prov.dataSourceUri()) dem_raster = gdal.Open(dem_path) projdsm = osr.SpatialReference(wkt=dem_raster.GetProjection()) projdsm.AutoIdentifyEPSG() projdsmepsg = int(projdsm.GetAttrValue('AUTHORITY', 1)) dem_crs = QgsCoordinateReferenceSystem(projdsmepsg) # dem_wkt = dem_raster.GetProjection() # dem_crs = osr.SpatialReference() # dem_crs.ImportFromWkt(dem_wkt) if can_crs != dem_crs: extentCanvas = self.iface.mapCanvas().extent() extentDEM = dem_layer.extent() transformExt = QgsCoordinateTransform(can_crs, dem_crs) # transformExt = osr.CoordinateTransformation(can_crs, dem_crs) canminx = extentCanvas.xMinimum() canmaxx = extentCanvas.xMaximum() canminy = extentCanvas.yMinimum() canmaxy = extentCanvas.yMaximum() canxymin = transformExt.TransformPoint(canminx, canminy) canxymax = transformExt.TransformPoint(canmaxx, canmaxy) extDiffminx = canxymin[0] - extentDEM.xMinimum( ) # If smaller than zero = warning extDiffminy = canxymin[1] - extentDEM.yMinimum( ) # If smaller than zero = warning extDiffmaxx = canxymax[0] - extentDEM.xMaximum( ) # If larger than zero = warning extDiffmaxy = canxymax[0] - extentDEM.yMaximum( ) # If larger than zero = warning if extDiffminx < 0 or extDiffminy < 0 or extDiffmaxx > 0 or extDiffmaxy > 0: QMessageBox.warning( None, "Warning! Extent of map canvas is larger than raster extent.", "Change to an extent equal to or smaller than the raster extent." ) return # Extent self.yMax = self.dlg.lineEditNorth.text() self.yMin = self.dlg.lineEditSouth.text() self.xMin = self.dlg.lineEditWest.text() self.xMax = self.dlg.lineEditEast.text() if not self.DSMoutputfile: QMessageBox.critical(None, "Error", "Specify a raster output file") return if self.dlg.checkBoxPolygon.isChecked() and not self.OSMoutputfile: QMessageBox.critical(None, "Error", "Specify an output file for OSM data") return # Acquiring geodata and attributes dem_layer = self.layerComboManagerDEM.currentLayer() if dem_layer is None: QMessageBox.critical(None, "Error", "No valid raster layer is selected") return else: provider = dem_layer.dataProvider() filepath_dem = str(provider.dataSourceUri()) demRaster = gdal.Open(filepath_dem) dem_layer_crs = osr.SpatialReference() dem_layer_crs.ImportFromWkt(demRaster.GetProjection()) self.dem_layer_unit = dem_layer_crs.GetAttrValue("UNIT") posUnits = [ 'metre', 'US survey foot', 'meter', 'm', 'ft', 'feet', 'foot', 'ftUS', 'International foot' ] # Possible units if not self.dem_layer_unit in posUnits: QMessageBox.critical( None, "Error", "Raster projection is not in metre or foot. Please reproject.") return polygon_layer = self.layerComboManagerPolygon.currentLayer() osm_layer = self.dlg.checkBoxOSM.isChecked() if polygon_layer is None and osm_layer is False: QMessageBox.critical(None, "Error", "No valid building height layer is selected") return elif polygon_layer: vlayer = QgsVectorLayer(polygon_layer.source(), "buildings", "ogr") fileInfo = QFileInfo(polygon_layer.source()) polygon_ln = fileInfo.baseName() polygon_field = self.layerComboManagerPolygonField.currentField() idx = vlayer.fieldNameIndex(polygon_field) flname = vlayer.attributeDisplayName(idx) if idx == -1: QMessageBox.critical( None, "Error", "An attribute with unique fields must be selected") return ### main code ### self.dlg.progressBar.setRange(0, 5) self.dlg.progressBar.setValue(1) if self.dlg.checkBoxOSM.isChecked(): # TODO replace osr.CoordinateTransformation with QgsCoordinateTransform dem_original = gdal.Open(filepath_dem) dem_wkt = dem_original.GetProjection() ras_crs = osr.SpatialReference() ras_crs.ImportFromWkt(dem_wkt) rasEPSG = ras_crs.GetAttrValue("PROJCS|AUTHORITY", 1) if self.dlg.layerButton.isChecked(): old_crs = ras_crs elif self.dlg.canvasButton.isChecked(): canvasCRS = self.iface.mapCanvas() outputWkt = canvasCRS.mapRenderer().destinationCrs().toWkt() old_crs = osr.SpatialReference() old_crs.ImportFromWkt(outputWkt) wgs84_wkt = """ GEOGCS["WGS 84", DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0, AUTHORITY["EPSG","8901"]], UNIT["degree",0.01745329251994328, AUTHORITY["EPSG","9122"]], AUTHORITY["EPSG","4326"]]""" new_crs = osr.SpatialReference() new_crs.ImportFromWkt(wgs84_wkt) transform = osr.CoordinateTransformation(old_crs, new_crs) minx = float(self.xMin) miny = float(self.yMin) maxx = float(self.xMax) maxy = float(self.yMax) lonlatmin = transform.TransformPoint(minx, miny) lonlatmax = transform.TransformPoint(maxx, maxy) if ras_crs != old_crs: rasTrans = osr.CoordinateTransformation(old_crs, ras_crs) raslonlatmin = rasTrans.TransformPoint(float(self.xMin), float(self.yMin)) raslonlatmax = rasTrans.TransformPoint(float(self.xMax), float(self.yMax)) #else: #raslonlatmin = [float(self.xMin), float(self.yMin)] #raslonlatmax = [float(self.xMax), float(self.yMax)] self.xMin = raslonlatmin[0] self.yMin = raslonlatmin[1] self.xMax = raslonlatmax[0] self.yMax = raslonlatmax[1] # Make data queries to overpass-api urlStr = 'http://overpass-api.de/api/map?bbox=' + str( lonlatmin[0]) + ',' + str(lonlatmin[1]) + ',' + str( lonlatmax[0]) + ',' + str(lonlatmax[1]) osmXml = urllib.urlopen(urlStr).read() #print urlStr # Make OSM building file osmPath = self.plugin_dir + '/temp/OSM_building.osm' osmFile = open(osmPath, 'w') osmFile.write(osmXml) if os.fstat(osmFile.fileno()).st_size < 1: urlStr = 'http://api.openstreetmap.org/api/0.6/map?bbox=' + str( lonlatmin[0]) + ',' + str(lonlatmin[1]) + ',' + str( lonlatmax[0]) + ',' + str(lonlatmax[1]) osmXml = urllib.urlopen(urlStr).read() osmFile.write(osmXml) #print 'Open Street Map' if os.fstat(osmFile.fileno()).st_size < 1: QMessageBox.critical(None, "Error", "No OSM data available") return osmFile.close() outputshp = self.plugin_dir + '/temp/' osmToShape = gdal_os_dep + 'ogr2ogr --config OSM_CONFIG_FILE "' + self.plugin_dir + '/osmconf.ini" -skipfailures -t_srs EPSG:' + str( rasEPSG ) + ' -overwrite -nlt POLYGON -f "ESRI Shapefile" "' + outputshp + '" "' + osmPath + '"' if sys.platform == 'win32': si = subprocess.STARTUPINFO() si.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call(osmToShape, startupinfo=si) else: os.system(osmToShape) driver = ogr.GetDriverByName('ESRI Shapefile') driver.DeleteDataSource(outputshp + 'lines.shp') driver.DeleteDataSource(outputshp + 'multilinestrings.shp') driver.DeleteDataSource(outputshp + 'other_relations.shp') driver.DeleteDataSource(outputshp + 'points.shp') osmPolygonPath = outputshp + 'multipolygons.shp' vlayer = QgsVectorLayer(osmPolygonPath, 'multipolygons', 'ogr') polygon_layer = vlayer fileInfo = QFileInfo(polygon_layer.source()) polygon_ln = fileInfo.baseName() def renameField(srcLayer, oldFieldName, newFieldName): ds = gdal.OpenEx(srcLayer.source(), gdal.OF_VECTOR | gdal.OF_UPDATE) ds.ExecuteSQL('ALTER TABLE {} RENAME COLUMN {} TO {}'.format( srcLayer.name(), oldFieldName, newFieldName)) srcLayer.reload() vlayer.startEditing() renameField(vlayer, 'building_l', 'bld_levels') renameField(vlayer, 'building_h', 'bld_hght') renameField(vlayer, 'building_c', 'bld_colour') renameField(vlayer, 'building_m', 'bld_materi') renameField(vlayer, 'building_u', 'bld_use') vlayer.commitChanges() vlayer.startEditing() vlayer.dataProvider().addAttributes( [QgsField('bld_height', QVariant.Double, 'double', 3, 2)]) vlayer.updateFields() bld_lvl = vlayer.fieldNameIndex('bld_levels') hght = vlayer.fieldNameIndex('height') bld_hght = vlayer.fieldNameIndex('bld_hght') bld_height = vlayer.fieldNameIndex('bld_height') bldLvlHght = float(self.dlg.doubleSpinBoxBldLvl.value()) illegal_chars = string.ascii_letters + "!#$%&'*+^_`|~:" + " " counterNone = 0 counter = 0 #counterWeird = 0 for feature in vlayer.getFeatures(): if feature[hght]: try: #feature[bld_height] = float(re.sub("[^0-9]", ".", str(feature[hght]))) feature[bld_height] = float( str(feature[hght]).translate(None, illegal_chars)) except: counterNone += 1 elif feature[bld_hght]: try: #feature[bld_height] = float(re.sub("[^0-9]", ".", str(feature[bld_hght]))) feature[bld_height] = float( str(feature[bld_hght]).translate( None, illegal_chars)) except: counterNone += 1 elif feature[bld_lvl]: try: #feature[bld_height] = float(re.sub("[^0-9]", "", str(feature[bld_lvl])))*bldLvlHght feature[bld_height] = float( str(feature[bld_lvl]).translate( None, illegal_chars)) * bldLvlHght except: counterNone += 1 else: counterNone += 1 vlayer.updateFeature(feature) counter += 1 vlayer.commitChanges() flname = vlayer.attributeDisplayName(bld_height) counterDiff = counter - counterNone # Zonal statistics vlayer.startEditing() zoneStat = QgsZonalStatistics(vlayer, filepath_dem, "stat_", 1, QgsZonalStatistics.Mean) zoneStat.calculateStatistics(None) vlayer.dataProvider().addAttributes( [QgsField('height_asl', QVariant.Double)]) vlayer.updateFields() e = QgsExpression('stat_mean + ' + flname) e.prepare(vlayer.pendingFields()) idx = vlayer.fieldNameIndex('height_asl') for f in vlayer.getFeatures(): f[idx] = e.evaluate(f) vlayer.updateFeature(f) vlayer.commitChanges() vlayer.startEditing() idx2 = vlayer.fieldNameIndex('stat_mean') vlayer.dataProvider().deleteAttributes([idx2]) vlayer.updateFields() vlayer.commitChanges() self.dlg.progressBar.setValue(2) # Convert polygon layer to raster # Define pixel_size and NoData value of new raster pixel_size = self.dlg.spinBox.value() # half picture size # Create the destination data source gdalrasterize = gdal_os_dep + 'gdal_rasterize -a ' + 'height_asl' + ' -te ' + str(self.xMin) + ' ' + str(self.yMin) + ' ' + str(self.xMax) + ' ' + str(self.yMax) +\ ' -tr ' + str(pixel_size) + ' ' + str(pixel_size) + ' -l "' + str(polygon_ln) + '" "' \ + str(polygon_layer.source()) + '" "' + self.plugin_dir + '/temp/clipdsm.tif"' # gdalclipdem = gdal_os_dep + 'gdalwarp -dstnodata -9999 -q -overwrite -te ' + str(self.xMin) + ' ' + str(self.yMin) + ' ' + str(self.xMax) + ' ' + str(self.yMax) +\ # ' -tr ' + str(pixel_size) + ' ' + str(pixel_size) + \ # ' -of GTiff ' + '"' + filepath_dem + '" "' + self.plugin_dir + '/temp/clipdem.tif"' # Rasterize if sys.platform == 'win32': si = subprocess.STARTUPINFO() si.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call(gdalrasterize, startupinfo=si) # subprocess.call(gdalclipdem, startupinfo=si) gdal.Warp(self.plugin_dir + '/temp/clipdem.tif', filepath_dem, xRes=pixel_size, yRes=pixel_size) else: os.system(gdalrasterize) # os.system(gdalclipdem) gdal.Warp(self.plugin_dir + '/temp/clipdem.tif', filepath_dem, xRes=pixel_size, yRes=pixel_size) # Remove gdalwarp with gdal.Translate # bigraster = gdal.Open(filepath_dem) # bbox = (self.xMin, self.yMax, self.xMax, self.yMin) # gdal.Translate(self.plugin_dir + '/data/clipdem.tif', bigraster, projWin=bbox) self.dlg.progressBar.setValue(3) # Adding DSM to DEM # Read DEM dem_raster = gdal.Open(self.plugin_dir + '/temp/clipdem.tif') dem_array = np.array(dem_raster.ReadAsArray().astype(np.float)) dsm_raster = gdal.Open(self.plugin_dir + '/temp/clipdsm.tif') dsm_array = np.array(dsm_raster.ReadAsArray().astype(np.float)) indx = dsm_array.shape for ix in range(0, int(indx[0])): for iy in range(0, int(indx[1])): if int(dsm_array[ix, iy]) == 0: dsm_array[ix, iy] = dem_array[ix, iy] if self.dlg.checkBoxPolygon.isChecked(): vlayer.startEditing() idxHght = vlayer.fieldNameIndex('height_asl') idxBld = vlayer.fieldNameIndex('building') features = vlayer.getFeatures() #for f in vlayer.getFeatures(): for f in features: geom = f.geometry() posUnitsMetre = ['metre', 'meter', 'm'] # Possible metre units posUnitsFt = [ 'US survey foot', 'ft', 'feet', 'foot', 'ftUS', 'International foot' ] # Possible foot units if self.dem_layer_unit in posUnitsMetre: sqUnit = 1 elif self.dem_layer_unit in posUnitsFt: sqUnit = 10.76 if int(geom.area()) > 50000 * sqUnit: vlayer.deleteFeature(f.id()) #if not f[idxHght]: #vlayer.deleteFeature(f.id()) #elif not f[idxBld]: #vlayer.deleteFeature(f.id()) vlayer.updateFields() vlayer.commitChanges() QgsVectorFileWriter.writeAsVectorFormat(vlayer, str(self.OSMoutputfile), "UTF-8", None, "ESRI Shapefile") else: vlayer.startEditing() idx3 = vlayer.fieldNameIndex('height_asl') vlayer.dataProvider().deleteAttributes([idx3]) vlayer.updateFields() vlayer.commitChanges() self.dlg.progressBar.setValue(4) # Save raster def saveraster( gdal_data, filename, raster ): # gdal_data = raster extent, filename = output filename, raster = numpy array (raster to be saved) rows = gdal_data.RasterYSize cols = gdal_data.RasterXSize outDs = gdal.GetDriverByName("GTiff").Create( filename, cols, rows, int(1), gdal.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()) saveraster(dsm_raster, self.DSMoutputfile, dsm_array) # Load result into canvas rlayer = self.iface.addRasterLayer(self.DSMoutputfile) # Trigger a repaint if hasattr(rlayer, "setCacheImage"): rlayer.setCacheImage(None) rlayer.triggerRepaint() self.dlg.progressBar.setValue(5) #runTime = datetime.datetime.now() - start if self.dlg.checkBoxOSM.isChecked(): QMessageBox.information( self.dlg, 'DSM Generator', 'Operation successful! ' + str(counterDiff) + ' building polygons out of ' + str(counter) + ' contained height values.') #self.iface.messageBar().pushMessage("DSM Generator. Operation successful! " + str(counterDiff) + " buildings out of " + str(counter) + " contained height values.", level=QgsMessageBar.INFO, duration=5) else: #self.iface.messageBar().pushMessage("DSM Generator. Operation successful!", level=QgsMessageBar.INFO, duration=5) QMessageBox.information(self.dlg, 'DSM Generator', 'Operation successful!') self.resetPlugin()
def processing(options, f, progressBar, progressMessage): ''' Select trees which are on the contour of the forest and isolated trees. ''' # Export Grid contour and isolated to crowns values forestSelectedPath = options['dst'] + 'tif/' + f + \ '_forest_selected.tif' crownsPath = options['dst'] + 'shp/' + f + '_crowns.shp' # crownsStatsPath = options['dst'] + 'shp/' + f + '_crowns_stats.shp' outputDir = options["dst"] fileTxt = open(outputDir + "/log.txt", "a") fileTxt.write("gridstatisticsforpolygons started\n") fileTxt.close() crowns = QgsVectorLayer(crownsPath, "crowns", "ogr") inputStatRaster = QgsRasterLayer(forestSelectedPath, "forestSelected") z_stat = QgsZonalStatistics(crowns, inputStatRaster, '_', 1, QgsZonalStatistics.Max) result_z_stat = z_stat.calculateStatistics(QgsFeedback()) outputDir = options["dst"] fileTxt = open(outputDir + "/log.txt", "a") fileTxt.write("gridstatisticsforpolygons passed\n") fileTxt.close() # crowns = QgsVectorLayer(crownsStatsPath, 'Crowns stats', 'ogr') crowns.selectByExpression('"_max"=1.0') selected_array = crowns.getValues("N", True) crowns.invertSelection() unselected_array = crowns.getValues("N", True) unselected_crowns_ids = crowns.getValues("$id", True) unselected_top_ids = crowns.getValues('"N" - 1', True) crowns.dataProvider().deleteFeatures(unselected_crowns_ids[0]) treetopsPath = options['dst'] + 'shp/' + f + '_treetops.shp' treetops = QgsVectorLayer(treetopsPath, 'Tree tops', 'ogr') treetops.dataProvider().deleteFeatures(unselected_top_ids[0]) treetopsSelectedPath = options['dst'] + 'shp/' + f + \ '_treetops_selected.shp' crownsSelectedPath = options['dst'] + 'shp/' + f + '_crowns_selected.shp' treetopsTrianglesPath = options['dst'] + 'shp/' + f + \ '_treetops_triangles.shp' outputDir = options["dst"] fileTxt = open(outputDir + "/log.txt", "a") fileTxt.write("advancedpythonfieldcalculator started\n") fileTxt.close() treetops.dataProvider().addAttributes([QgsField('N', QVariant.Int)]) treetops.updateFields() treetops.startEditing() for treetop in treetops.getFeatures(): treetops.changeAttributeValue(treetop.id(), treetop.fieldNameIndex('N'), treetop.id()) treetops.commitChanges() outputDir = options["dst"] fileTxt = open(outputDir + "/log.txt", "a") fileTxt.write("joinattributesbylocation started\n") fileTxt.close() # Adapted from https://github.com/qgis/QGIS-Processing # TODO: replace by native QGIS c++ algo when available... crowns.dataProvider().addAttributes([QgsField('tid', QVariant.Int)]) crowns.updateFields() crowns.startEditing() fcount = crowns.featureCount() counter = 0 for crown in crowns.getFeatures(): counter += 1 progressBar.setValue(100 + int(counter * (600 / fcount))) progressMessage.setText('Joining crown ' + str(counter) + '/' + str(fcount)) request = QgsFeatureRequest() request.setFilterRect(crown.geometry().boundingBox()) dp = treetops.dataProvider() for r in dp.getFeatures(request): if crown.geometry().intersects(r.geometry()): crowns.changeAttributeValue(crown.id(), crown.fieldNameIndex('tid'), r.id()) crowns.commitChanges() fileTxt = open(outputDir + "/log.txt", "a") fileTxt.write("delaunaytriangulation started\n") fileTxt.close() # delaunay triangulation Adapted from official Python plugin # TODO: replace by native QGIS c++ algo when available... fields = QgsFields() fields.append(QgsField('POINTA', QVariant.Double, '', 24, 15)) fields.append(QgsField('POINTB', QVariant.Double, '', 24, 15)) fields.append(QgsField('POINTC', QVariant.Double, '', 24, 15)) crs = QgsCoordinateReferenceSystem('EPSG:2056') triangleFile = QgsVectorFileWriter(treetopsTrianglesPath, 'utf-8', fields, QgsWkbTypes.Polygon, crs, 'ESRI Shapefile') pts = [] ptDict = {} ptNdx = -1 c = voronoi.Context() features = treetops.getFeatures() total = 100.0 / treetops.featureCount() if treetops.featureCount() else 0 progressMessage.setText('Starting triangulation...') for current, inFeat in enumerate(features): geom = QgsGeometry(inFeat.geometry()) if geom.isNull(): continue if geom.isMultipart(): points = geom.asMultiPoint() else: points = [geom.asPoint()] for n, point in enumerate(points): x = point.x() y = point.y() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = (inFeat.id(), n) progressMessage.setText('Triangulation step 1 ok') if len(pts) < 3: raise QgsProcessingException( 'Input file should contain at least 3 points. Choose ' 'another file and try again.') uniqueSet = set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet]) c.triangulate = True voronoi.voronoi(sl, c) triangles = c.triangles feat = QgsFeature() total = 100.0 / len(triangles) if triangles else 1 for current, triangle in enumerate(triangles): indices = list(triangle) indices.append(indices[0]) polygon = [] attrs = [] step = 0 for index in indices: fid, n = ptDict[ids[index]] request = QgsFeatureRequest().setFilterFid(fid) inFeat = next(treetops.getFeatures(request)) geom = QgsGeometry(inFeat.geometry()) point = QgsPoint(geom.asPoint()) polygon.append(point) if step <= 3: attrs.append(ids[index]) step += 1 linestring = QgsLineString(polygon) poly = QgsPolygon() poly.setExteriorRing(linestring) feat.setAttributes(attrs) geometry = QgsGeometry().fromWkt(poly.asWkt()) feat.setGeometry(geometry) triangleFile.addFeature(feat) progressMessage.setText('Triangulation terminated') # Remove triangles with perimeter higher than threshold triangles = QgsVectorLayer(treetopsTrianglesPath, 'triangles', 'ogr') maxPeri = str(options['MaxTrianglePerimeter']) triangles.selectByExpression('$perimeter > ' + maxPeri) triangles_to_delete_ids = triangles.getValues("$id", True) triangles.dataProvider().deleteFeatures(triangles_to_delete_ids[0]) outputDir = options["dst"] fileTxt = open(outputDir + "/log.txt", "a") fileTxt.write("treeSelector passed\n") fileTxt.close() progressMessage.setText('Starting convexhull computing...')
indicators = [['LiveBirths18', 'cparish']] for indicator in indicators: print('--- Computing statistics for the indicator ' + indicator[0]) shape_portugal = QgsVectorLayer('/mnt/joao/Pycharm/disseverap_VDF/Shapefiles/' + indicator[1] + '13_cont.shp', 'zonepolygons', 'ogr') dir_2evaluate = os.path.join('/mnt/joao/Pycharm/disseverap_VDF/Results', indicator[0], '2Evaluate') if os.path.isdir(dir_2evaluate): for name_file in os.listdir(dir_2evaluate): file_2evaluate = os.path.join(dir_2evaluate, name_file) if os.path.isfile(file_2evaluate): raster = QgsRasterLayer(file_2evaluate) zoneStat = QgsZonalStatistics (shape_portugal, raster, '', 1, QgsZonalStatistics.Sum) zoneStat.calculateStatistics(None) idx = shape_portugal.dataProvider().fieldNameIndex('sum') shape_portugal.startEditing() shape_portugal.renameAttribute(idx, 'VALUE') shape_portugal.commitChanges() createopts=['SEPARATOR=SEMICOLON'] name_file = name_file.replace('.tif', '') name_out = os.path.join('/mnt/joao/Pycharm/disseverap_VDF/Estimates', indicator[0], '2Evaluate', name_file) + '.csv' QgsVectorFileWriter.writeAsVectorFormat(shape_portugal, name_out, 'utf-8', driverName='CSV', layerOptions=createopts) shape_portugal.dataProvider().deleteAttributes([idx]) shape_portugal.updateFields() destination = str('/mnt/joao/Pycharm/disseverap_VDF/Results/' + indicator[0] + '/' + name_file + '.tif') os.rename(file_2evaluate, destination)
polygonLayer = QgsVectorLayer('/home/arturs/Downloads/SHP/landus_A.shp', 'zonepolygons', "ogr") subfolders = [ f.name for f in os.scandir('/home/arturs/Data/RGB_Tiles/') if f.is_dir() ] for subfolder in subfolders: filelist = [file for file in os.listdir('/home/arturs/Data/RGB_Tiles/' + subfolder) if file.endswith('.tif')] for file in filelist: # specify raster filename rasterFilePath = '/home/arturs/Data/RGB_Tiles/' + subfolder + '/' + file rasterFile = QgsRasterLayer(rasterFilePath, 'raster') # usage - QgsZonalStatistics (QgsVectorLayer *polygonLayer, const QString &rasterFile, const QString &attributePrefix="", int rasterBand=1) zoneStat = QgsZonalStatistics (polygonLayer, rasterFile, '', 1, QgsZonalStatistics.Count) zoneStat.calculateStatistics(None) shapefile = "/home/arturs/Downloads/SHP/landus_A.shp" driver = ogr.GetDriverByName("ESRI Shapefile") dataSource = driver.Open(shapefile, 0) layer = dataSource.GetLayer() layer.SetAttributeFilter("count = 50176") if layer.GetFeatureCount()==1: for feature in layer: x = feature.GetField("FNAME") shutil.copy(rasterFilePath, '/home/arturs/Data/LandUse/' + x) # read header automatically with open('/home/arturs/Data/LandUse/train.csv', "r", encoding="utf-8") as train_file: reader = csv.reader(train_file)
"""Run this script within the QGIS Python console.""" from qgis.analysis import QgsZonalStatistics # Add polygon layer uri = QgsDataSourceURI() uri.setConnection("localhost", "5432", "coastalheat", "postgres", "ownwardenter") uri.setDataSource("public", "coastalwaters", "geometry") zones = QgsVectorLayer(uri.uri(), "coastalwaters", "postgres") # Raster layer connStr = "PG: dbname=coastalHeat user=postgres password=ownwardenter " \ + "mode=2 schema=public column=rast table=sst" # Calculate zonal statistics zonalStats = QgsZonalStatistics(zones, connStr, "", 1, QgsZonalStatistics.Mean) zonalStats.calculateStatistics(None)
from qgis.analysis import QgsZonalStatistics from qgis.core import * from qgis.utils import * from timeit import default_timer as timer from time import sleep import yaml with open('/opt/data/rasterScripts/populationTif.yaml') as f: # use safe_load instead load dataMap = yaml.safe_load(f) for i in dataMap: print "Starting " + i['detailLabel'] + " aka " + i["prefixColumn"] #Symlinks to the TIF files does not work #Use the layer already loaded in QGIS by command line options polygonLayer = iface.activeLayer() print "Found layer:", iface.activeLayer() zoneStat = QgsZonalStatistics(polygonLayer, i["filePath"], i["prefixColumn"]) start = timer() oneOutput = zoneStat.calculateStatistics(None) end = timer() print "Done-" + i["prefixColumn"] + str(oneOutput) + " in " + str( end - start) QgsApplication.exitQgis() QgsApplication.exitQgis()
import sys import numpy as np import matplotlib.pyplot as plt from qgis.analysis import QgsZonalStatistics canvas = qgis.utils.iface.mapCanvas() layers = canvas.layers() layers[0].name() layers[1].name() for x in range(366): zoneStat = QgsZonalStatistics(layers[0], layers[1], '_', x, QgsZonalStatistics.Mean) zoneStat.calculateStatistics(None)
# Add the number of pixels overlapping with the mandatory growthfactor layers... # Create QgsVectorLayer object polygonLayer = QgsVectorLayer(ineligible_pixels_poly, ineligible_pixels_poly_layername, "ogr") polygonLayer.startEditing() # Loop over all raster layers to add zonal statistics to the vector layer... mandatory_growthfactor_list = mandatory_growthfactor_inputs.split(';') lvhelper.log("Loop through all raster layers to add statistics...") for i, input_raster in enumerate(mandatory_growthfactor_list): # usage - QgsZonalStatistics (QgsVectorLayer *polygonLayer, const QString &rasterFile, const QString &attributePrefix="", int rasterBand=1) lvhelper.log(" - Adding statistics from raster file " + input_raster + " ...") zoneStat = QgsZonalStatistics( polygonLayer, input_raster, ("m" + str(i + 1) + "_"), 1, QgsZonalStatistics.Count | QgsZonalStatistics.Mean) zoneStat.calculateStatistics(None) polygonLayer.commitChanges() # Create the select statement needed to calculate the number of mandatory pixels... full_pixel_area = rasterUnitsPerPixelX * rasterUnitsPerPixelY * 4 # the full pixel area needs a multiplication by 4 because we created smaller pixels compared to the native pixels to increase the accuracy!!! max_mandatory_pixels_area_formula = '0.25*{full_pixel_area}'.format( full_pixel_area=full_pixel_area) for i, input_raster in enumerate(mandatory_growthfactor_list): if i == 0: max_mandatory_pixels_area_formula = 'MAX(' max_mandatory_pixels_area_formula += ("IFNULL(m" + str(i + 1) + "_count, 0)") if i < (len(mandatory_growthfactor_list) - 1):