def mmi_to_shapefile(self, force_flag=False): """Convert grid.xml's mmi column to a vector shp file using ogr2ogr. An ESRI shape file will be created. :param force_flag: bool (Optional). Whether to force the regeneration of the output file. Defaults to False. :return: Path to the resulting tif file. :rtype: str Example of the ogr2ogr call we generate:: ogr2ogr -select mmi -a_srs EPSG:4326 mmi.shp mmi.vrt mmi .. note:: It is assumed that ogr2ogr is in your path. """ LOGGER.debug('mmi_to_shapefile requested.') shp_path = os.path.join(self.output_dir, '%s-points.shp' % self.output_basename) # Short circuit if the tif is already created. if os.path.exists(shp_path) and force_flag is not True: return shp_path # Ensure the vrt mmi file exists (it will generate csv too if needed) vrt_path = self.mmi_to_vrt(force_flag) # now generate the tif using default interpolation options binary_list = which('ogr2ogr') LOGGER.debug('Path for ogr2ogr: %s' % binary_list) if len(binary_list) < 1: raise CallGDALError( tr('ogr2ogr could not be found on your computer')) # Use the first matching gdalwarp found binary = binary_list[0] command = (('%(ogr2ogr)s -overwrite -select mmi -a_srs EPSG:4326 ' '%(shp)s %(vrt)s mmi') % { 'ogr2ogr': binary, 'shp': shp_path, 'vrt': vrt_path }) LOGGER.info('Created this ogr command:\n%s' % command) # Now run ogr2ogr ... # noinspection PyProtectedMember self._run_command(command) # Lastly copy over the standard qml (QGIS Style file) for the mmi.tif qml_path = os.path.join(self.output_dir, '%s-points.qml' % self.output_basename) source_qml = resources_path('converter_data', 'mmi-shape.qml') shutil.copyfile(source_qml, qml_path) return shp_path
def mmi_to_shapefile(self, force_flag=False): """Convert grid.xml's mmi column to a vector shp file using ogr2ogr. An ESRI shape file will be created. :param force_flag: bool (Optional). Whether to force the regeneration of the output file. Defaults to False. :return: Path to the resulting tif file. :rtype: str Example of the ogr2ogr call we generate:: ogr2ogr -select mmi -a_srs EPSG:4326 mmi.shp mmi.vrt mmi .. note:: It is assumed that ogr2ogr is in your path. """ LOGGER.debug('mmi_to_shapefile requested.') shp_path = os.path.join( self.output_dir, '%s-points.shp' % self.output_basename) # Short circuit if the tif is already created. if os.path.exists(shp_path) and force_flag is not True: return shp_path # Ensure the vrt mmi file exists (it will generate csv too if needed) vrt_path = self.mmi_to_vrt(force_flag) # now generate the tif using default interpolation options binary_list = which('ogr2ogr') LOGGER.debug('Path for ogr2ogr: %s' % binary_list) if len(binary_list) < 1: raise CallGDALError( tr('ogr2ogr could not be found on your computer')) # Use the first matching gdalwarp found binary = binary_list[0] command = ( ('%(ogr2ogr)s -overwrite -select mmi -a_srs EPSG:4326 ' '%(shp)s %(vrt)s mmi') % { 'ogr2ogr': binary, 'shp': shp_path, 'vrt': vrt_path}) LOGGER.info('Created this ogr command:\n%s' % command) # Now run ogr2ogr ... # noinspection PyProtectedMember self._run_command(command) # Lastly copy over the standard qml (QGIS Style file) for the mmi.tif qml_path = os.path.join( self.output_dir, '%s-points.qml' % self.output_basename) source_qml = os.path.join(data_dir(), 'mmi-shape.qml') shutil.copyfile(source_qml, qml_path) return shp_path
def _clip_raster_layer( layer, extent, cell_size=None, extra_keywords=None): """Clip a Hazard or Exposure raster layer to the extents provided. The layer must be a raster layer or an exception will be thrown. .. note:: The extent *must* be in EPSG:4326. The output layer will always be in WGS84/Geographic. :param layer: A valid QGIS raster layer in EPSG:4326 :type layer: QgsRasterLayer :param extent: An array representing the exposure layer extents in the form [xmin, ymin, xmax, ymax]. It is assumed that the coordinates are in EPSG:4326 although currently no checks are made to enforce this. or: A QgsGeometry of type polygon. **Polygon clipping currently only supported for vector datasets.** :type extent: list(float), QgsGeometry :param cell_size: Cell size (in GeoCRS) which the layer should be resampled to. If not provided for a raster layer (i.e. theCellSize=None), the native raster cell size will be used. :type cell_size: float :returns: Output clipped layer (placed in the system temp dir). :rtype: QgsRasterLayer :raises: InvalidProjectionError - if input layer is a density layer in projected coordinates. See issue #123. """ if not layer or not extent: message = tr('Layer or Extent passed to clip is None.') raise InvalidParameterError(message) if layer.type() != QgsMapLayer.RasterLayer: message = tr( 'Expected a raster layer but received a %s.' % str(layer.type())) raise InvalidParameterError(message) working_layer = layer.source() # Check for existence of keywords file base, _ = os.path.splitext(working_layer) keywords_path = base + '.xml' message = tr( 'Input file to be clipped "%s" does not have the ' 'expected keywords file %s' % ( working_layer, keywords_path )) verify(os.path.isfile(keywords_path), message) # Raise exception if layer is projected and refers to density (issue #123) # FIXME (Ole): Need to deal with it - e.g. by automatically reprojecting # the layer at this point and setting the native resolution accordingly # in its keywords. try: keywords = read_iso19115_metadata(working_layer) except (MetadataReadError, NoKeywordsFoundError): keywords = read_keywords(base + '.keywords') keywords = write_read_iso_19115_metadata(working_layer, keywords) if 'datatype' in keywords and keywords['datatype'] == 'count': if str(layer.crs().authid()) != 'EPSG:4326': # This layer is not WGS84 geographic message = ( 'Layer %s represents count but has spatial reference "%s". ' 'Count layers must be given in WGS84 geographic coordinates, ' 'so please reproject and try again. For more information, see ' 'issue https://github.com/AIFDR/inasafe/issues/123' % ( working_layer, layer.crs().toProj4() )) raise InvalidProjectionError(message) # We need to provide gdalwarp with a dataset for the clip # because unlike gdal_translate, it does not take projwin. clip_kml = extent_to_kml(extent) # Create a filename for the clipped, resampled and reprojected layer handle, filename = tempfile.mkstemp('.tif', 'clip_', temp_dir()) os.close(handle) os.remove(filename) # If no cell size is specified, we need to run gdalwarp without # specifying the output pixel size to ensure the raster dims # remain consistent. binary_list = which('gdalwarp') LOGGER.debug('Path for gdalwarp: %s' % binary_list) if len(binary_list) < 1: raise CallGDALError( tr('gdalwarp could not be found on your computer')) # Use the first matching gdalwarp found binary = binary_list[0] if cell_size is None: command = ( '"%s" -q -t_srs EPSG:4326 -r near -cutline %s -crop_to_cutline ' '-ot Float64 -of GTiff "%s" "%s"' % ( binary, clip_kml, working_layer, filename)) else: command = ( '"%s" -q -t_srs EPSG:4326 -r near -tr %s %s -cutline %s ' '-crop_to_cutline -ot Float64 -of GTiff "%s" "%s"' % ( binary, repr(cell_size), repr(cell_size), clip_kml, working_layer, filename)) LOGGER.debug(command) result = QProcess().execute(command) # For QProcess exit codes see # http://qt-project.org/doc/qt-4.8/qprocess.html#execute if result == -2: # cannot be started message_detail = tr('Process could not be started.') message = tr( '<p>Error while executing the following shell command:' '</p><pre>%s</pre><p>Error message: %s' % (command, message_detail)) raise CallGDALError(message) elif result == -1: # process crashed message_detail = tr('Process crashed.') message = tr( '<p>Error while executing the following shell command:</p>' '<pre>%s</pre><p>Error message: %s' % (command, message_detail)) raise CallGDALError(message) # .. todo:: Check the result of the shell call is ok keyword_io = KeywordIO() keyword_io.copy_keywords(layer, filename, extra_keywords=extra_keywords) base_name = '%s clipped' % layer.name() layer = QgsRasterLayer(filename, base_name) return layer
def mmi_to_raster(self, force_flag=False, algorithm='nearest'): """Convert the grid.xml's mmi column to a raster using gdal_grid. A geotiff file will be created. Unfortunately no python bindings exist for doing this so we are going to do it using a shell call. .. see also:: http://www.gdal.org/gdal_grid.html Example of the gdal_grid call we generate:: gdal_grid -zfield "mmi" -a invdist:power=2.0:smoothing=1.0 \ -txe 126.29 130.29 -tye 0.802 4.798 -outsize 400 400 -of GTiff \ -ot Float16 -l mmi mmi.vrt mmi.tif .. note:: It is assumed that gdal_grid is in your path. :param force_flag: Whether to force the regeneration of the output file. Defaults to False. :type force_flag: bool :param algorithm: Which re-sampling algorithm to use. valid options are 'nearest' (for nearest neighbour), 'invdist' (for inverse distance), 'average' (for moving average). Defaults to 'nearest' if not specified. Note that passing re-sampling alg parameters is currently not supported. If None is passed it will be replaced with 'nearest'. :type algorithm: str :returns: Path to the resulting tif file. :rtype: str .. note:: For interest you can also make quite beautiful smoothed raster using this: gdal_grid -zfield "mmi" -a_srs EPSG:4326 -a invdist:power=2.0:smoothing=1.0 -txe 122.45 126.45 -tye -2.21 1.79 -outsize 400 400 -of GTiff -ot Float16 -l mmi mmi.vrt mmi-trippy.tif """ LOGGER.debug('mmi_to_raster requested.') if algorithm is None: algorithm = 'nearest' if self.algorithm_name: tif_path = os.path.join( self.output_dir, '%s-%s.tif' % (self.output_basename, algorithm)) else: tif_path = os.path.join(self.output_dir, '%s.tif' % self.output_basename) # short circuit if the tif is already created. if os.path.exists(tif_path) and force_flag is not True: return tif_path # Ensure the vrt mmi file exists (it will generate csv too if needed) vrt_path = self.mmi_to_vrt(force_flag) # now generate the tif using default nearest neighbour interpolation # options. This gives us the same output as the mi.grd generated by # the earthquake server. if 'invdist' in algorithm: algorithm = 'invdist:power=2.0:smoothing=1.0' # (Sunni): I'm not sure how this 'mmi' will work # (Tim): Its the mapping to which field in the CSV contains the data # to be gridded. command = (('%(gdal_grid)s -a %(alg)s -zfield "mmi" -txe %(xMin)s ' '%(xMax)s -tye %(yMin)s %(yMax)s -outsize %(dimX)i ' '%(dimY)i -of GTiff -ot Float16 -a_srs EPSG:4326 -l mmi ' '"%(vrt)s" "%(tif)s"') % { 'gdal_grid': which('gdal_grid')[0], 'alg': algorithm, 'xMin': self.x_minimum, 'xMax': self.x_maximum, 'yMin': self.y_minimum, 'yMax': self.y_maximum, 'dimX': self.columns, 'dimY': self.rows, 'vrt': vrt_path, 'tif': tif_path }) LOGGER.info('Created this gdal command:\n%s' % command) # Now run GDAL warp scottie... self._run_command(command) # We will use keywords file name with simple algorithm name since it # will raise an error in windows related to having double colon in path if 'invdist' in algorithm: algorithm = 'invdist' # copy the keywords file from fixtures for this layer self.create_keyword_file(algorithm) # Lastly copy over the standard qml (QGIS Style file) for the mmi.tif if self.algorithm_name: qml_path = os.path.join( self.output_dir, '%s-%s.qml' % (self.output_basename, algorithm)) else: qml_path = os.path.join(self.output_dir, '%s.qml' % self.output_basename) qml_source_path = os.path.join(data_dir(), 'mmi.qml') shutil.copyfile(qml_source_path, qml_path) return tif_path
def mmi_to_raster( self, force_flag=False, algorithm='nearest'): """Convert the grid.xml's mmi column to a raster using gdal_grid. A geotiff file will be created. Unfortunately no python bindings exist for doing this so we are going to do it using a shell call. .. see also:: http://www.gdal.org/gdal_grid.html Example of the gdal_grid call we generate:: gdal_grid -zfield "mmi" -a invdist:power=2.0:smoothing=1.0 \ -txe 126.29 130.29 -tye 0.802 4.798 -outsize 400 400 -of GTiff \ -ot Float16 -l mmi mmi.vrt mmi.tif .. note:: It is assumed that gdal_grid is in your path. :param force_flag: Whether to force the regeneration of the output file. Defaults to False. :type force_flag: bool :param algorithm: Which re-sampling algorithm to use. valid options are 'nearest' (for nearest neighbour), 'invdist' (for inverse distance), 'average' (for moving average). Defaults to 'nearest' if not specified. Note that passing re-sampling alg parameters is currently not supported. If None is passed it will be replaced with 'nearest'. :type algorithm: str :returns: Path to the resulting tif file. :rtype: str .. note:: For interest you can also make quite beautiful smoothed raster using this: gdal_grid -zfield "mmi" -a_srs EPSG:4326 -a invdist:power=2.0:smoothing=1.0 -txe 122.45 126.45 -tye -2.21 1.79 -outsize 400 400 -of GTiff -ot Float16 -l mmi mmi.vrt mmi-trippy.tif """ LOGGER.debug('mmi_to_raster requested.') if algorithm is None: algorithm = 'nearest' if self.algorithm_name: tif_path = os.path.join( self.output_dir, '%s-%s.tif' % ( self.output_basename, algorithm)) else: tif_path = os.path.join( self.output_dir, '%s.tif' % self.output_basename) # short circuit if the tif is already created. if os.path.exists(tif_path) and force_flag is not True: return tif_path # Ensure the vrt mmi file exists (it will generate csv too if needed) vrt_path = self.mmi_to_vrt(force_flag) # now generate the tif using default nearest neighbour interpolation # options. This gives us the same output as the mi.grd generated by # the earthquake server. if 'invdist' in algorithm: algorithm = 'invdist:power=2.0:smoothing=1.0' # (Sunni): I'm not sure how this 'mmi' will work # (Tim): Its the mapping to which field in the CSV contains the data # to be gridded. command = (( '%(gdal_grid)s -a %(alg)s -zfield "mmi" -txe %(xMin)s ' '%(xMax)s -tye %(yMin)s %(yMax)s -outsize %(dimX)i ' '%(dimY)i -of GTiff -ot Float16 -a_srs EPSG:4326 -l mmi ' '"%(vrt)s" "%(tif)s"') % { 'gdal_grid': which('gdal_grid')[0], 'alg': algorithm, 'xMin': self.x_minimum, 'xMax': self.x_maximum, 'yMin': self.y_minimum, 'yMax': self.y_maximum, 'dimX': self.columns, 'dimY': self.rows, 'vrt': vrt_path, 'tif': tif_path }) LOGGER.info('Created this gdal command:\n%s' % command) # Now run GDAL warp scottie... self._run_command(command) # We will use keywords file name with simple algorithm name since it # will raise an error in windows related to having double colon in path if 'invdist' in algorithm: algorithm = 'invdist' # copy the keywords file from fixtures for this layer self.create_keyword_file(algorithm) # Lastly copy over the standard qml (QGIS Style file) for the mmi.tif if self.algorithm_name: qml_path = os.path.join( self.output_dir, '%s-%s.qml' % ( self.output_basename, algorithm)) else: qml_path = os.path.join( self.output_dir, '%s.qml' % self.output_basename) qml_source_path = os.path.join(data_dir(), 'mmi.qml') shutil.copyfile(qml_source_path, qml_path) return tif_path
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 test_which(self): """Test that the which command works as expected.""" binary = 'gdalwarp' path = which(binary) # Check we found at least one match assert len(path) > 0
def _clip_raster_layer( layer, extent, cell_size=None, extra_keywords=None): """Clip a Hazard or Exposure raster layer to the extents provided. The layer must be a raster layer or an exception will be thrown. .. note:: The extent *must* be in EPSG:4326. The output layer will always be in WGS84/Geographic. :param layer: A valid QGIS raster layer in EPSG:4326 :type layer: QgsRasterLayer :param extent: An array representing the exposure layer extents in the form [xmin, ymin, xmax, ymax]. It is assumed that the coordinates are in EPSG:4326 although currently no checks are made to enforce this. or: A QgsGeometry of type polygon. **Polygon clipping currently only supported for vector datasets.** :type extent: list(float), QgsGeometry :param cell_size: Cell size (in GeoCRS) which the layer should be resampled to. If not provided for a raster layer (i.e. theCellSize=None), the native raster cell size will be used. :type cell_size: float :returns: Output clipped layer (placed in the system temp dir). :rtype: QgsRasterLayer :raises: InvalidProjectionError - if input layer is a density layer in projected coordinates. See issue #123. """ if not layer or not extent: message = tr('Layer or Extent passed to clip is None.') raise InvalidParameterError(message) if layer.type() != QgsMapLayer.RasterLayer: message = tr( 'Expected a raster layer but received a %s.' % str(layer.type())) raise InvalidParameterError(message) working_layer = layer.source() # Check for existence of keywords file base, _ = os.path.splitext(working_layer) keywords_path = base + '.keywords' message = tr( 'Input file to be clipped "%s" does not have the ' 'expected keywords file %s' % ( working_layer, keywords_path )) verify(os.path.isfile(keywords_path), message) # Raise exception if layer is projected and refers to density (issue #123) # FIXME (Ole): Need to deal with it - e.g. by automatically reprojecting # the layer at this point and setting the native resolution accordingly # in its keywords. keywords = read_file_keywords(keywords_path) if 'datatype' in keywords and keywords['datatype'] == 'count': if str(layer.crs().authid()) != 'EPSG:4326': # This layer is not WGS84 geographic message = ( 'Layer %s represents count but has spatial reference "%s". ' 'Count layers must be given in WGS84 geographic coordinates, ' 'so please reproject and try again. For more information, see ' 'issue https://github.com/AIFDR/inasafe/issues/123' % ( working_layer, layer.crs().toProj4() )) raise InvalidProjectionError(message) # We need to provide gdalwarp with a dataset for the clip # because unlike gdal_translate, it does not take projwin. clip_kml = extent_to_kml(extent) # Create a filename for the clipped, resampled and reprojected layer handle, filename = tempfile.mkstemp('.tif', 'clip_', temp_dir()) os.close(handle) os.remove(filename) # If no cell size is specified, we need to run gdalwarp without # specifying the output pixel size to ensure the raster dims # remain consistent. binary_list = which('gdalwarp') LOGGER.debug('Path for gdalwarp: %s' % binary_list) if len(binary_list) < 1: raise CallGDALError( tr('gdalwarp could not be found on your computer')) # Use the first matching gdalwarp found binary = binary_list[0] if cell_size is None: command = ( '"%s" -q -t_srs EPSG:4326 -r near -cutline %s -crop_to_cutline ' '-ot Float64 -of GTiff "%s" "%s"' % ( binary, clip_kml, working_layer, filename)) else: command = ( '"%s" -q -t_srs EPSG:4326 -r near -tr %s %s -cutline %s ' '-crop_to_cutline -ot Float64 -of GTiff "%s" "%s"' % ( binary, repr(cell_size), repr(cell_size), clip_kml, working_layer, filename)) LOGGER.debug(command) result = QProcess().execute(command) # For QProcess exit codes see # http://qt-project.org/doc/qt-4.8/qprocess.html#execute if result == -2: # cannot be started message_detail = tr('Process could not be started.') message = tr( '<p>Error while executing the following shell command:' '</p><pre>%s</pre><p>Error message: %s' % (command, message_detail)) raise CallGDALError(message) elif result == -1: # process crashed message_detail = tr('Process crashed.') message = tr( '<p>Error while executing the following shell command:</p>' '<pre>%s</pre><p>Error message: %s' % (command, message_detail)) raise CallGDALError(message) # .. todo:: Check the result of the shell call is ok keyword_io = KeywordIO() keyword_io.copy_keywords(layer, filename, extra_keywords=extra_keywords) base_name = '%s clipped' % layer.name() layer = QgsRasterLayer(filename, base_name) return layer
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