예제 #1
0
    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
예제 #2
0
    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
예제 #3
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 + '.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
예제 #4
0
    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
예제 #5
0
    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
예제 #6
0
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
예제 #7
0
 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
예제 #8
0
파일: clipper.py 프로젝트: kant/inasafe
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
예제 #9
0
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