def rasterize_vector_layer(layer, width, height, extent): """Rasterize a vector layer to the grid given by extent and width/height. :param layer: The vector layer. :type layer: QgsVectorLayer :param width: The width of the output. :type width: int :param height: The height of the output. :type height: int :param extent: The extent to use. :type extent: QgsRectangle :return: The new raster layer. :rtype: QgsRasterLayer """ name = rasterize_steps['gdal_layer_name'] output_filename = unique_filename(prefix=name, suffix='.tif') extent_str = '%f,%f,%f,%f' % (extent.xMinimum(), extent.xMaximum(), extent.yMinimum(), extent.yMaximum()) keywords = dict(layer.keywords) # The layer is in memory, we need to save it to a file for Processing. data_store = Folder(mkdtemp()) data_store.default_vector_format = 'geojson' result = data_store.add_layer(layer, 'vector_layer') layer = data_store.layer(result[1]) assert layer.isValid() field = layer.keywords['inasafe_fields'][aggregation_id_field['key']] # ET 21/02/17. I got some issues using rasterize algorithm from Processing. # I keep it in case of we need it later. Let's use gdal command line. use_gdal_command_line = True if use_gdal_command_line: startupinfo = None if sys.platform == 'win32': # On windows, we don't want to display the bash shell. # https://github.com/inasafe/inasafe/issues/3980 startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW commands = [which('gdal_rasterize')[0]] commands += ['-a', field] commands += ['-ts', str(width), str(height)] commands += ['-ot', 'Int16'] commands += ['-a_nodata', "'-1'"] commands += [layer.source(), output_filename] LOGGER.info(' '.join(commands)) result = subprocess.check_call(commands, startupinfo=startupinfo) LOGGER.info('Result : %s' % result) else: parameters = dict() parameters['INPUT'] = layer parameters['FIELD'] = field parameters['DIMENSIONS'] = 0 # output size is given in pixels parameters['WIDTH'] = width parameters['HEIGHT'] = height parameters['RASTER_EXT'] = extent_str parameters['TFW'] = False # force generation of ESRI TFW parameters['RTYPE'] = 1 # raster type: Int16 parameters['NO_DATA'] = '-1' # nodata value parameters['COMPRESS'] = 4 # GeoTIFF compression: DEFLATE parameters['JPEGCOMPRESSION'] = 75 # JPEG compression level: 75 parameters['ZLEVEL'] = 6 # DEFLATE compression level parameters['PREDICTOR'] = 1 # predictor for JPEG/DEFLATE parameters['TILED'] = False # Tiled GeoTIFF? parameters['BIGTIFF'] = 0 # whether to make big TIFF parameters['EXTRA'] = '' # additional creation parameters parameters['OUTPUT'] = output_filename result = runalg('gdalogr:rasterize', parameters) if result is None: # Let's try be removing a new parameter added between 2.14 and 2.16 del parameters['RASTER_EXT'] result = runalg('gdalogr:rasterize', parameters) assert result is not None layer_aligned = QgsRasterLayer(output_filename, name, 'gdal') assert layer_aligned.isValid() layer_aligned.keywords = keywords layer_aligned.keywords['title'] = (rasterize_steps['output_layer_name'] % 'aggregation') layer_aligned.keywords['layer_purpose'] = ( layer_purpose_aggregation_summary['key']) del layer_aligned.keywords['inasafe_fields'] check_layer(layer_aligned) return layer_aligned
def reclassify(layer, exposure_key=None, overwrite_input=False, callback=None): """Reclassify a continuous raster layer. Issue https://github.com/inasafe/inasafe/issues/3182 This function is a wrapper for the code from https://github.com/chiatt/gdal_reclassify For instance if you want to reclassify like this table : Original Value | Class - ∞ < val <= 0 | 1 0 < val <= 0.5 | 2 0.5 < val <= 5 | 3 5 < val < + ∞ | 6 You need a dictionary : ranges = OrderedDict() ranges[1] = [None, 0] ranges[2] = [0.0, 0.5] ranges[3] = [0.5, 5] ranges[6] = [5, None] :param layer: The raster layer. :type layer: QgsRasterLayer :param overwrite_input: Option for the output layer. True will overwrite the input layer. False will create a temporary layer. :type overwrite_input: bool :param exposure_key: The exposure key. :type exposure_key: str :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 classified raster layer. :rtype: QgsRasterLayer .. versionadded:: 4.0 """ output_layer_name = reclassify_raster_steps['output_layer_name'] processing_step = reclassify_raster_steps['step_name'] output_layer_name = output_layer_name % layer.keywords['layer_purpose'] if exposure_key: classification_key = active_classification(layer.keywords, exposure_key) thresholds = active_thresholds_value_maps(layer.keywords, exposure_key) layer.keywords['thresholds'] = thresholds layer.keywords['classification'] = classification_key else: classification_key = layer.keywords.get('classification') thresholds = layer.keywords.get('thresholds') if not thresholds: raise InvalidKeywordsForProcessingAlgorithm( 'thresholds are missing from the layer %s' % layer.keywords['layer_purpose']) if not classification_key: raise InvalidKeywordsForProcessingAlgorithm( 'classification is missing from the layer %s' % layer.keywords['layer_purpose']) ranges = {} value_map = {} hazard_classes = definition(classification_key)['classes'] for hazard_class in hazard_classes: ranges[hazard_class['value']] = thresholds[hazard_class['key']] value_map[hazard_class['key']] = [hazard_class['value']] if overwrite_input: output_raster = layer.source() else: output_raster = unique_filename(suffix='.tiff', dir=temp_dir()) driver = gdal.GetDriverByName('GTiff') raster_file = gdal.Open(layer.source()) band = raster_file.GetRasterBand(1) no_data = band.GetNoDataValue() source = band.ReadAsArray() destination = source.copy() for value, interval in ranges.iteritems(): v_min = interval[0] v_max = interval[1] if v_min is None: destination[np.where(source <= v_max)] = value if v_max is None: destination[np.where(source > v_min)] = value if v_min < v_max: destination[np.where((v_min < source) & (source <= v_max))] = value # Tag no data cells destination[np.where(source == no_data)] = no_data_value # Create the new file. output_file = driver.Create(output_raster, raster_file.RasterXSize, raster_file.RasterYSize, 1) output_file.GetRasterBand(1).WriteArray(destination) output_file.GetRasterBand(1).SetNoDataValue(no_data_value) # CRS output_file.SetProjection(raster_file.GetProjection()) output_file.SetGeoTransform(raster_file.GetGeoTransform()) output_file.FlushCache() del output_file if not isfile(output_raster): raise FileNotFoundError reclassified = QgsRasterLayer(output_raster, output_layer_name) # We transfer keywords to the output. reclassified.keywords = layer.keywords.copy() reclassified.keywords['layer_mode'] = 'classified' value_map = {} hazard_classes = definition(classification_key)['classes'] for hazard_class in reversed(hazard_classes): value_map[hazard_class['key']] = [hazard_class['value']] reclassified.keywords['value_map'] = value_map reclassified.keywords['title'] = output_layer_name check_layer(reclassified) return reclassified
def align_rasters(hazard_layer, exposure_layer, extent): """Align hazard and exposure raster layers. Align hazard and exposure raster layers so they fit perfectly and so they can be used for raster algebra. The method uses QGIS raster alignment tool to do the work (which in turn uses GDAL). Alignment of layers means that the layers have the same CRS, cell size, grid origin and size. That involves clipping and resampling of rasters. From the two layers, the layer with finer resolution (smaller cell size) will be used as the reference for the alignment (i.e. parameters will be set to its CRS, cell size and grid offset). - Reproject to the same CRS. - Resample to the same cell size and offset in the grid. - Clip to a region of interest. :param hazard_layer: Hazard layer to be aligned. :type hazard_layer: QgsRasterLayer :param exposure_layer: Exposure layer to be aligned. :type exposure_layer: QgsRasterLayer :param extent: Extent in exposure CRS to which raster should be clipped. :type extent: QgsRectangle :return: Clipped hazard and exposure layers. :rtype: QgsRasterLayer, QgsRasterLayer """ output_layer_name = align_steps['output_layer_name'] processing_step = align_steps['step_name'] hazard_output = unique_filename(suffix='.tif') exposure_output = unique_filename(suffix='.tif') # Setup the two raster layers for alignment align = QgsAlignRaster() inputs = [ QgsAlignRaster.Item(hazard_layer.source(), hazard_output), QgsAlignRaster.Item(exposure_layer.source(), exposure_output) ] if exposure_layer.keywords.get('exposure_unit') == 'count': inputs[1].rescaleValues = True align.setRasters(inputs) # Find out which layer has finer grid and use it as the reference. # This will setup destination CRS, cell size and grid origin if exposure_layer.keywords.get('allow_resampling', True): index = align.suggestedReferenceLayer() else: index = 1 # have to use exposure layer as the reference if index < 0: raise AlignRastersError(tr('Unable to select reference layer')) if not align.setParametersFromRaster( inputs[index].inputFilename, exposure_layer.crs().toWkt()): raise AlignRastersError(align.errorMessage()) # Setup clip extent align.setClipExtent(extent) # Everything configured - do the alignment now! # For each raster, it will create output file and write resampled values if not align.run(): raise AlignRastersError(align.errorMessage()) # Load resulting layers aligned_hazard_layer = QgsRasterLayer( hazard_output, output_layer_name % 'hazard') aligned_exposure_layer = QgsRasterLayer( exposure_output, output_layer_name % 'exposure') aligned_hazard_layer.keywords = dict(hazard_layer.keywords) aligned_hazard_layer.keywords['title'] = output_layer_name % 'hazard' aligned_exposure_layer.keywords = dict(exposure_layer.keywords) aligned_exposure_layer.keywords['title'] = output_layer_name % 'exposure' # avoid any possible further rescaling of exposure data by correctly # setting original resolution to be the same as current resolution aligned_exposure_layer.keywords['resolution'] = ( align.cellSize().width(), align.cellSize().height()) check_layer(exposure_layer) check_layer(hazard_layer) return aligned_hazard_layer, aligned_exposure_layer
def clip_by_extent(layer, extent, callback=None): """Clip a raster using a bounding box using processing. Issue https://github.com/inasafe/inasafe/issues/3183 :param layer: The layer to reproject. :type layer: QgsRasterLayer :param extent: The extent. :type extent: QgsRectangle :param callback: A function to all to indicate progress. The function should accept params 'current' (int) and 'maximum' (int). Defaults to None. :type callback: function :return: Reprojected memory layer. :rtype: QgsRasterLayer .. versionadded:: 4.0 """ parameters = dict() # noinspection PyBroadException try: output_layer_name = quick_clip_steps['output_layer_name'] processing_step = quick_clip_steps['step_name'] output_layer_name = output_layer_name % layer.keywords['layer_purpose'] output_raster = unique_filename(dir=temp_dir()) # We make one pixel size buffer on the extent to cover every pixels. # See https://github.com/inasafe/inasafe/issues/3655 pixel_size_x = layer.rasterUnitsPerPixelX() pixel_size_y = layer.rasterUnitsPerPixelY() buffer_size = max(pixel_size_x, pixel_size_y) extent = extent.buffer(buffer_size) if is_raster_y_inverted(layer): # The raster is Y inverted. We need to switch Y min and Y max. bbox = [ str(extent.xMinimum()), str(extent.xMaximum()), str(extent.yMaximum()), str(extent.yMinimum()) ] else: # The raster is normal. bbox = [ str(extent.xMinimum()), str(extent.xMaximum()), str(extent.yMinimum()), str(extent.yMaximum()) ] # These values are all from the processing algorithm. # https://github.com/qgis/QGIS/blob/master/python/plugins/processing/ # algs/gdal/ClipByExtent.py # Please read the file to know these parameters. parameters['INPUT'] = layer.source() parameters['NO_DATA'] = '' parameters['PROJWIN'] = ','.join(bbox) parameters['RTYPE'] = 5 parameters['COMPRESS'] = 4 parameters['JPEGCOMPRESSION'] = 75 parameters['ZLEVEL'] = 6 parameters['PREDICTOR'] = 1 parameters['TILED'] = False parameters['BIGTIFF'] = 0 parameters['TFW'] = False parameters['EXTRA'] = '' parameters['OUTPUT'] = output_raster result = processing.runalg("gdalogr:cliprasterbyextent", parameters) if result is None: raise ProcessingInstallationError clipped = QgsRasterLayer(result['OUTPUT'], output_layer_name) # We transfer keywords to the output. clipped.keywords = layer.keywords.copy() clipped.keywords['title'] = output_layer_name check_layer(clipped) except Exception as e: # This step clip_raster_by_extent was nice to speedup the analysis. # As we got an exception because the layer is invalid, we are not going # to stop the analysis. We will return the original raster layer. # It will take more processing time until we clip the vector layer. # Check https://github.com/inasafe/inasafe/issues/4026 why we got some # exceptions with this step. LOGGER.exception(parameters) LOGGER.exception( 'Error from QGIS clip raster by extent. Please check the QGIS ' 'logs too !') LOGGER.info( 'Even if we got an exception, we are continuing the analysis. The ' 'layer is not clip.') LOGGER.exception(str(e)) LOGGER.exception(get_error_message(e).to_text()) clipped = layer return clipped
def clip_by_extent(layer, extent): """Clip a raster using a bounding box using processing. Issue https://github.com/inasafe/inasafe/issues/3183 :param layer: The layer to clip. :type layer: QgsRasterLayer :param extent: The extent. :type extent: QgsRectangle :return: Clipped layer. :rtype: QgsRasterLayer .. versionadded:: 4.0 """ parameters = dict() # noinspection PyBroadException try: output_layer_name = quick_clip_steps['output_layer_name'] output_layer_name = output_layer_name % layer.keywords['layer_purpose'] output_raster = unique_filename(suffix='.tif', dir=temp_dir()) # We make one pixel size buffer on the extent to cover every pixels. # See https://github.com/inasafe/inasafe/issues/3655 pixel_size_x = layer.rasterUnitsPerPixelX() pixel_size_y = layer.rasterUnitsPerPixelY() buffer_size = max(pixel_size_x, pixel_size_y) extent = extent.buffered(buffer_size) if is_raster_y_inverted(layer): # The raster is Y inverted. We need to switch Y min and Y max. bbox = [ str(extent.xMinimum()), str(extent.xMaximum()), str(extent.yMaximum()), str(extent.yMinimum()) ] else: # The raster is normal. bbox = [ str(extent.xMinimum()), str(extent.xMaximum()), str(extent.yMinimum()), str(extent.yMaximum()) ] # These values are all from the processing algorithm. # https://github.com/qgis/QGIS/blob/master/python/plugins/processing/ # algs/gdal/ClipByExtent.py # Please read the file to know these parameters. parameters['INPUT'] = layer.source() parameters['NO_DATA'] = '' parameters['PROJWIN'] = ','.join(bbox) parameters['DATA_TYPE'] = 5 parameters['COMPRESS'] = 4 parameters['JPEGCOMPRESSION'] = 75 parameters['ZLEVEL'] = 6 parameters['PREDICTOR'] = 1 parameters['TILED'] = False parameters['BIGTIFF'] = 0 parameters['TFW'] = False parameters['EXTRA'] = '' parameters['OUTPUT'] = output_raster initialize_processing() feedback = create_processing_feedback() context = create_processing_context(feedback=feedback) result = processing.run( "gdal:cliprasterbyextent", parameters, context=context) if result is None: raise ProcessingInstallationError clipped = QgsRasterLayer(result['OUTPUT'], output_layer_name) # We transfer keywords to the output. clipped.keywords = layer.keywords.copy() clipped.keywords['title'] = output_layer_name check_layer(clipped) except Exception as e: # This step clip_raster_by_extent was nice to speedup the analysis. # As we got an exception because the layer is invalid, we are not going # to stop the analysis. We will return the original raster layer. # It will take more processing time until we clip the vector layer. # Check https://github.com/inasafe/inasafe/issues/4026 why we got some # exceptions with this step. LOGGER.exception(parameters) LOGGER.exception( 'Error from QGIS clip raster by extent. Please check the QGIS ' 'logs too !') LOGGER.info( 'Even if we got an exception, we are continuing the analysis. The ' 'layer was not clipped.') LOGGER.exception(str(e)) LOGGER.exception(get_error_message(e).to_text()) clipped = layer return clipped
def exposed_people_stats(hazard, exposure, aggregation): """Calculate the number of exposed people per MMI level per aggregation. Calculate the number of exposed people per MMI level per aggregation zone and prepare raster layer outputs. :param hazard: The earthquake raster layer. :type hazard: QgsRasterLayer :param exposure: The population raster layer. :type exposure: QgsVectorLayer :param aggregation: The aggregation layer. :type aggregation: QgsVectorLayer :return: A tuble with the exposed per MMI level par aggregation and the exposed raster. Tuple (mmi, agg_zone), value: number of exposed people :rtype: (dict, QgsRasterLayer) """ output_layer_name = earthquake_displaced['output_layer_name'] processing_step = earthquake_displaced['step_name'] exposed_raster_filename = unique_filename(prefix=output_layer_name, suffix='.tif') hazard_provider = hazard.dataProvider() extent = hazard.extent() width, height = hazard_provider.xSize(), hazard_provider.ySize() hazard_block = hazard_provider.block(1, extent, width, height) exposure_provider = exposure.dataProvider() exposure_block = exposure_provider.block(1, extent, width, height) agg_provider = aggregation.dataProvider() agg_block = agg_provider.block(1, extent, width, height) exposed = {} # key: tuple (mmi, agg_zone), value: number of exposed people exposed_array = make_array(width, height) classification_key = hazard.keywords['classification'] # walk through the rasters pixel by pixel and aggregate numbers # of people in the combination of hazard zones and aggregation zones for i in xrange(width * height): hazard_mmi = hazard_block.value(long(i)) people_count = exposure_block.value(long(i)) agg_zone_index = int(agg_block.value(long(i))) if hazard_mmi >= 2.0 and people_count >= 0.0: hazard_mmi = int(round(hazard_mmi)) mmi_fatality_rate = fatality_rate(hazard_mmi, classification_key) mmi_fatalities = int( # rounding down people_count * mmi_fatality_rate) mmi_displaced = ((people_count - mmi_fatalities) * displacement_rate(hazard_mmi, classification_key)) key = (hazard_mmi, agg_zone_index) if key not in exposed: exposed[key] = 0 exposed[key] += people_count else: # If hazard is less than 2 or population is less than 0 mmi_displaced = -1 # We build a raster only for the aggregation area. if agg_zone_index > 0: exposed_array[i / width, i % width] = mmi_displaced else: exposed_array[i / width, i % width] = -1 # output raster data - e.g. displaced people array_to_raster(exposed_array, exposed_raster_filename, hazard) # I didn't find a way to do that with the QGIS API. data = gdal.Open(exposed_raster_filename, gdalconst.GA_Update) data.GetRasterBand(1).SetNoDataValue(-1) del data exposed_raster = QgsRasterLayer(exposed_raster_filename, 'exposed', 'gdal') assert exposed_raster.isValid() exposed_raster.keywords = dict(exposure.keywords) exposed_raster.keywords['layer_purpose'] = ( layer_purpose_exposure_summary['key']) exposed_raster.keywords['title'] = processing_step exposed_raster.keywords['exposure_keywords'] = dict(exposure.keywords) exposed_raster.keywords['hazard_keywords'] = dict(hazard.keywords) exposed_raster.keywords['aggregation_keywords'] = dict( aggregation.keywords) return exposed, exposed_raster
def reclassify(layer, exposure_key=None, overwrite_input=False, callback=None): """Reclassify a continuous raster layer. Issue https://github.com/inasafe/inasafe/issues/3182 This function is a wrapper for the code from https://github.com/chiatt/gdal_reclassify For instance if you want to reclassify like this table : Original Value | Class - ∞ < val <= 0 | 1 0 < val <= 0.5 | 2 0.5 < val <= 5 | 3 5 < val < + ∞ | 6 You need a dictionary : ranges = OrderedDict() ranges[1] = [None, 0] ranges[2] = [0.0, 0.5] ranges[3] = [0.5, 5] ranges[6] = [5, None] :param layer: The raster layer. :type layer: QgsRasterLayer :param overwrite_input: Option for the output layer. True will overwrite the input layer. False will create a temporary layer. :type overwrite_input: bool :param exposure_key: The exposure key. :type exposure_key: str :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 classified raster layer. :rtype: QgsRasterLayer .. versionadded:: 4.0 """ output_layer_name = reclassify_raster_steps['output_layer_name'] processing_step = reclassify_raster_steps['step_name'] output_layer_name = output_layer_name % layer.keywords['layer_purpose'] if exposure_key: classification_key = active_classification( layer.keywords, exposure_key) thresholds = active_thresholds_value_maps(layer.keywords, exposure_key) layer.keywords['thresholds'] = thresholds layer.keywords['classification'] = classification_key else: classification_key = layer.keywords.get('classification') thresholds = layer.keywords.get('thresholds') if not thresholds: raise InvalidKeywordsForProcessingAlgorithm( 'thresholds are missing from the layer %s' % layer.keywords['layer_purpose']) if not classification_key: raise InvalidKeywordsForProcessingAlgorithm( 'classification is missing from the layer %s' % layer.keywords['layer_purpose']) ranges = {} value_map = {} hazard_classes = definition(classification_key)['classes'] for hazard_class in hazard_classes: ranges[hazard_class['value']] = thresholds[hazard_class['key']] value_map[hazard_class['key']] = [hazard_class['value']] if overwrite_input: output_raster = layer.source() else: output_raster = unique_filename(suffix='.tiff', dir=temp_dir()) driver = gdal.GetDriverByName('GTiff') raster_file = gdal.Open(layer.source()) band = raster_file.GetRasterBand(1) no_data = band.GetNoDataValue() source = band.ReadAsArray() destination = source.copy() for value, interval in ranges.iteritems(): v_min = interval[0] v_max = interval[1] if v_min is None: destination[np.where(source <= v_max)] = value if v_max is None: destination[np.where(source > v_min)] = value if v_min < v_max: destination[np.where((v_min < source) & (source <= v_max))] = value # Tag no data cells destination[np.where(source == no_data)] = no_data_value # Create the new file. output_file = driver.Create( output_raster, raster_file.RasterXSize, raster_file.RasterYSize, 1) output_file.GetRasterBand(1).WriteArray(destination) output_file.GetRasterBand(1).SetNoDataValue(no_data_value) # CRS output_file.SetProjection(raster_file.GetProjection()) output_file.SetGeoTransform(raster_file.GetGeoTransform()) output_file.FlushCache() del output_file if not isfile(output_raster): raise FileNotFoundError reclassified = QgsRasterLayer(output_raster, output_layer_name) # We transfer keywords to the output. reclassified.keywords = layer.keywords.copy() reclassified.keywords['layer_mode'] = 'classified' value_map = {} hazard_classes = definition(classification_key)['classes'] for hazard_class in reversed(hazard_classes): value_map[hazard_class['key']] = [hazard_class['value']] reclassified.keywords['value_map'] = value_map reclassified.keywords['title'] = output_layer_name check_layer(reclassified) return reclassified
def rasterize_vector_layer(layer, width, height, extent): """Rasterize a vector layer to the grid given by extent and width/height. :param layer: The vector layer. :type layer: QgsVectorLayer :param width: The width of the output. :type width: int :param height: The height of the output. :type height: int :param extent: The extent to use. :type extent: QgsRectangle :return: The new raster layer. :rtype: QgsRasterLayer """ name = rasterize_steps['gdal_layer_name'] output_filename = unique_filename(prefix=name, suffix='.tif') extent_str = '%f,%f,%f,%f' % ( extent.xMinimum(), extent.xMaximum(), extent.yMinimum(), extent.yMaximum()) keywords = dict(layer.keywords) # The layer is in memory, we need to save it to a file for Processing. data_store = Folder(mkdtemp()) data_store.default_vector_format = 'geojson' result = data_store.add_layer(layer, 'vector_layer') layer = data_store.layer(result[1]) assert layer.isValid() field = layer.keywords['inasafe_fields'][aggregation_id_field['key']] # ET 21/02/17. I got some issues using rasterize algorithm from Processing. # I keep it in case of we need it later. Let's use gdal command line. use_gdal_command_line = True if use_gdal_command_line: startupinfo = None if sys.platform == 'win32': # On windows, we don't want to display the bash shell. # https://github.com/inasafe/inasafe/issues/3980 startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW commands = [which('gdal_rasterize')[0]] commands += ['-a', field] commands += ['-ts', str(width), str(height)] commands += ['-ot', 'Int16'] commands += ['-a_nodata', "'-1'"] commands += [layer.source(), output_filename] LOGGER.info(' '.join(commands)) result = subprocess.check_call(commands, startupinfo=startupinfo) LOGGER.info('Result : %s' % result) else: parameters = dict() parameters['INPUT'] = layer parameters['FIELD'] = field parameters['DIMENSIONS'] = 0 # output size is given in pixels parameters['WIDTH'] = width parameters['HEIGHT'] = height parameters['RASTER_EXT'] = extent_str parameters['TFW'] = False # force generation of ESRI TFW parameters['RTYPE'] = 1 # raster type: Int16 parameters['NO_DATA'] = '-1' # nodata value parameters['COMPRESS'] = 4 # GeoTIFF compression: DEFLATE parameters['JPEGCOMPRESSION'] = 75 # JPEG compression level: 75 parameters['ZLEVEL'] = 6 # DEFLATE compression level parameters['PREDICTOR'] = 1 # predictor for JPEG/DEFLATE parameters['TILED'] = False # Tiled GeoTIFF? parameters['BIGTIFF'] = 0 # whether to make big TIFF parameters['EXTRA'] = '' # additional creation parameters parameters['OUTPUT'] = output_filename result = runalg('gdalogr:rasterize', parameters) if result is None: # Let's try be removing a new parameter added between 2.14 and 2.16 del parameters['RASTER_EXT'] result = runalg('gdalogr:rasterize', parameters) assert result is not None layer_aligned = QgsRasterLayer(output_filename, name, 'gdal') assert layer_aligned.isValid() layer_aligned.keywords = keywords layer_aligned.keywords['title'] = ( rasterize_steps['output_layer_name'] % 'aggregation') layer_aligned.keywords['layer_purpose'] = ( layer_purpose_aggregation_summary['key']) del layer_aligned.keywords['inasafe_fields'] check_layer(layer_aligned) return layer_aligned