示例#1
0
    def read_keywords(self, layer, keyword=None):
        """Read keywords for a datasource and return them as a dictionary.

        This is a wrapper method that will 'do the right thing' to fetch
        keywords for the given datasource. In particular, if the datasource
        is remote (e.g. a database connection) it will fetch the keywords from
        the keywords store.

        :param layer:  A QGIS QgsMapLayer instance that you want to obtain
            the keywords for.
        :type layer: QgsMapLayer

        :param keyword: If set, will extract only the specified keyword
              from the keywords dict.
        :type keyword: str

        :returns: A dict if keyword is omitted, otherwise the value for the
            given key if it is present.
        :rtype: dict, str
        """
        mySource = str(layer.source())
        myFlag = self.are_keywords_file_based(layer)

        try:
            if myFlag:
                myKeywords = readKeywordsFromFile(mySource, keyword)
            else:
                myKeywords = self.read_keyword_from_uri(mySource, keyword)
            return myKeywords
        except (HashNotFoundError, Exception, OperationalError):
            raise
示例#2
0
    def read_keywords(self, layer, keyword=None):
        """Read keywords for a datasource and return them as a dictionary.

        This is a wrapper method that will 'do the right thing' to fetch
        keywords for the given datasource. In particular, if the datasource
        is remote (e.g. a database connection) it will fetch the keywords from
        the keywords store.

        :param layer:  A QGIS QgsMapLayer instance that you want to obtain
            the keywords for.
        :type layer: QgsMapLayer

        :param keyword: If set, will extract only the specified keyword
              from the keywords dict.
        :type keyword: str

        :returns: A dict if keyword is omitted, otherwise the value for the
            given key if it is present.
        :rtype: dict, str
        """
        mySource = str(layer.source())
        myFlag = self.are_keywords_file_based(layer)

        try:
            if myFlag:
                myKeywords = readKeywordsFromFile(mySource, keyword)
            else:
                myKeywords = self.read_keyword_from_uri(mySource, keyword)
            return myKeywords
        except (HashNotFoundError, Exception, OperationalError):
            raise
示例#3
0
    def readKeywords(self, theLayer, theKeyword=None):
        """Read keywords for a datasource and return them as a dictionary.
        This is a wrapper method that will 'do the right thing' to fetch
        keywords for the given datasource. In particular, if the datasource
        is remote (e.g. a database connection) it will fetch the keywords from
        the keywords store.

        Args:
            * theLayer - A QGIS QgsMapLayer instance.
            * theKeyword - optional - will extract only the specified keyword
              from the keywords dict.
        Returns:
            A dict if theKeyword is omitted, otherwise the value for the
            given key if it is present.
        Raises:
            Propogates any exception from the underlying reader delegate.
        """
        mySource = str(theLayer.source())
        myFlag = self.areKeywordsFileBased(theLayer)
        myKeywords = None

        try:
            if myFlag:
                myKeywords = readKeywordsFromFile(mySource, theKeyword)
            else:
                myKeywords = self.readKeywordFromUri(mySource, theKeyword)
            return myKeywords
        except (HashNotFoundException, Exception):
            raise
示例#4
0
    def readKeywords(self, theLayer, theKeyword=None):
        """Read keywords for a datasource and return them as a dictionary.
        This is a wrapper method that will 'do the right thing' to fetch
        keywords for the given datasource. In particular, if the datasource
        is remote (e.g. a database connection) it will fetch the keywords from
        the keywords store.

        Args:
            * theLayer - A QGIS QgsMapLayer instance.
            * theKeyword - optional - will extract only the specified keyword
              from the keywords dict.
        Returns:
            A dict if theKeyword is omitted, otherwise the value for the
            given key if it is present.
        Raises:
            Propogates any exception from the underlying reader delegate.
        """
        mySource = str(theLayer.source())
        myFlag = self.areKeywordsFileBased(theLayer)
        myKeywords = None

        try:
            if myFlag:
                myKeywords = readKeywordsFromFile(mySource, theKeyword)
            else:
                myKeywords = self.readKeywordFromUri(mySource, theKeyword)
            return myKeywords
        except (HashNotFoundException, Exception):
            raise
示例#5
0
def makePadangLayer():
    """Helper function that returns a single predefined layer"""
    myFile = 'Shakemap_Padang_2009.asc'
    myPath = os.path.join(HAZDATA, myFile)
    myTitle = readKeywordsFromFile(myPath, 'title')
    # myTitle = 'An earthquake in Padang like in 2009'
    myLayer = QgsRasterLayer(myPath, myTitle)
    QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer
示例#6
0
    def test_getKeywordFromFile(self):
        """Get keyword from a filesystem file's .keyword file."""

        myKeyword = readKeywordsFromFile(self.rasterShakePath, 'category')
        myExpectedKeyword = 'hazard'
        myMessage = 'Got: %s\n\nExpected %s\n\nDB: %s' % (
            myKeyword, myExpectedKeyword, self.rasterShakePath)
        assert myKeyword == 'hazard', myMessage

        # Test we get an exception if keyword is not found
        try:
            _ = readKeywordsFromFile(self.rasterShakePath, 'boguskeyword')
        except KeywordNotFoundError:
            pass  # this is good
        except Exception, e:
            myMessage = ('Request for bogus keyword raised incorrect '
                         'exception type: \n %s') % str(e)
            assert (), myMessage
def makePadangLayer():
    """Helper function that returns a single predefined layer"""
    myFile = 'Shakemap_Padang_2009.asc'
    myPath = os.path.join(HAZDATA, myFile)
    myTitle = readKeywordsFromFile(myPath, 'title')
    # myTitle = 'An earthquake in Padang like in 2009'
    myLayer = QgsRasterLayer(myPath, myTitle)
    QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer
示例#8
0
    def test_getKeywordFromFile(self):
        """Get keyword from a filesystem file's .keyword file."""

        myKeyword = readKeywordsFromFile(self.rasterShakePath, 'category')
        myExpectedKeyword = 'hazard'
        myMessage = 'Got: %s\n\nExpected %s\n\nDB: %s' % (
                    myKeyword, myExpectedKeyword, self.rasterShakePath)
        assert myKeyword == 'hazard', myMessage

        # Test we get an exception if keyword is not found
        try:
            _ = readKeywordsFromFile(self.rasterShakePath,
                                     'boguskeyword')
        except KeywordNotFoundError:
            pass  # this is good
        except Exception, e:
            myMessage = ('Request for bogus keyword raised incorrect '
                         'exception type: \n %s') % str(e)
            assert(), myMessage
    def test_availableFunctions(self):
        """Check we can get the available functions from the impact calculator.
        """
        myList = availableFunctions()
        myMessage = 'No functions available (len=%ss)' % len(myList)
        assert len(myList) > 0, myMessage

        # Also test if it works when we give it two layers
        # to see if we can determine which functions will
        # work for them.
        myKeywords1 = readKeywordsFromFile(self.rasterShakePath)
        myKeywords2 = readKeywordsFromFile(self.vectorPath)
        # We need to explicitly add the layer type to each keyword list
        myKeywords1['layertype'] = 'raster'
        myKeywords2['layertype'] = 'vector'

        myList = [myKeywords1, myKeywords2]
        myList = availableFunctions(myList)
        myMessage = 'No functions available (len=%ss)' % len(myList)
        assert len(myList) > 0, myMessage
示例#10
0
def makePointLayer():
    """Helper function that returns a single predefined layer"""
    myFile = 'test_buildings.shp'
    myPath = os.path.join(TESTDATA, myFile)
    try:
        myTitle = readKeywordsFromFile(myPath, 'title')
    except KeywordNotFoundError:
        myTitle = 'kabupaten_jakarta_singlepart_3_good_attr'
    myLayer = QgsVectorLayer(myPath, myTitle, 'ogr')
    QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer
示例#11
0
def makePointLayer():
    """Helper function that returns a single predefined layer"""
    myFile = 'test_buildings.shp'
    myPath = os.path.join(TESTDATA, myFile)
    try:
        myTitle = readKeywordsFromFile(myPath, 'title')
    except KeywordNotFoundException:
        myTitle = 'kabupaten_jakarta_singlepart_3_good_attr'
    myLayer = QgsVectorLayer(myPath, myTitle, 'ogr')
    QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer
示例#12
0
    def test_availableFunctions(self):
        """Check we can get the available functions from the impact calculator.
        """
        myList = availableFunctions()
        myMessage = 'No functions available (len=%ss)' % len(myList)
        assert len(myList) > 0, myMessage

        # Also test if it works when we give it two layers
        # to see if we can determine which functions will
        # work for them.
        myKeywords1 = readKeywordsFromFile(self.rasterShakePath)
        myKeywords2 = readKeywordsFromFile(self.vectorPath)
        # We need to explicitly add the layer type to each keyword list
        myKeywords1['layertype'] = 'raster'
        myKeywords2['layertype'] = 'vector'

        myList = [myKeywords1, myKeywords2]
        myList = availableFunctions(myList)
        myMessage = 'No functions available (len=%ss)' % len(myList)
        assert len(myList) > 0, myMessage
示例#13
0
def makePolygonLayer():
    """Helper function that returns a single predefined layer"""
    myFile = 'kabupaten_jakarta_singlepart_3_good_attr.shp'
    myPath = os.path.join(TESTDATA, myFile)
    try:
        myTitle = readKeywordsFromFile(myPath, 'title')
    except KeywordNotFoundError:
        myTitle = 'kabupaten_jakarta_singlepart_3_good_attr'
    myLayer = QgsVectorLayer(myPath, myTitle, 'ogr')
    if qgisVersion() >= 10800:  # 1.8 or newer
        QgsMapLayerRegistry.instance().addMapLayers([myLayer])
    else:
        QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer
示例#14
0
def makePadangLayer():
    """Helper function that returns a single predefined layer"""
    myFile = 'Shakemap_Padang_2009.asc'
    myPath = os.path.join(HAZDATA, myFile)
    myTitle = readKeywordsFromFile(myPath, 'title')
    # myTitle = 'An earthquake in Padang like in 2009'
    myLayer = QgsRasterLayer(myPath, myTitle)
    if qgis_version() >= 10800:  # 1.8 or newer
        # noinspection PyArgumentList
        QgsMapLayerRegistry.instance().addMapLayers([myLayer])
    else:
        # noinspection PyArgumentList
        QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer
示例#15
0
def makePolygonLayer():
    """Helper function that returns a single predefined layer"""
    myFile = 'kabupaten_jakarta_singlepart_3_good_attr.shp'
    myPath = os.path.join(TESTDATA, myFile)
    try:
        myTitle = readKeywordsFromFile(myPath, 'title')
    except KeywordNotFoundError:
        myTitle = 'kabupaten_jakarta_singlepart_3_good_attr'
    myLayer = QgsVectorLayer(myPath, myTitle, 'ogr')
    if qgisVersion() >= 10800:  # 1.8 or newer
        QgsMapLayerRegistry.instance().addMapLayers([myLayer])
    else:
        QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer
示例#16
0
def copyMakePadangLayer():
    """Helper function that copies padang keyword for testing and return it."""
    mySourceFileName = 'Shakemap_Padang_2009'
    myExts = ['.asc', '.asc.aux.xml', '.keywords',
              '.lic', '.prj', '.qml', '.sld']
    myFileName = unique_filename()
    # copy to temp file
    for ext in myExts:
        mySourcePath = os.path.join(HAZDATA, mySourceFileName + ext)
        myDestPath = os.path.join(HAZDATA, myFileName + ext)
        shutil.copy2(mySourcePath, myDestPath)
    # return a single predefined layer
    myFile = myFileName + '.asc'
    myPath = os.path.join(HAZDATA, myFile)
    myTitle = readKeywordsFromFile(myPath, 'title')
    myLayer = QgsRasterLayer(myPath, myTitle)
    QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer, myFileName
示例#17
0
def load_layer(layer_file, directory=TESTDATA):
    """Helper to load and return a single QGIS layer

    :param layer_file: Path name to raster or vector file.
    :type layer_file: str
    :param directory: Optional parent dir. If None, path name is assumed
        to be absolute.
    :type directory: str, None

    :returns: tuple containing layer and its category.
    :rtype: (QgsMapLayer, str)

    """

    # Extract basename and absolute path
    myFilename = os.path.split(layer_file)[-1]  # In case path was absolute
    myBaseName, myExt = os.path.splitext(myFilename)
    if directory is None:
        myPath = layer_file
    else:
        myPath = os.path.join(directory, layer_file)
    myKeywordPath = myPath[:-4] + '.keywords'

    # Determine if layer is hazard or exposure
    myKeywords = readKeywordsFromFile(myKeywordPath)
    myCategory = 'undefined'
    if 'category' in myKeywords:
        myCategory = myKeywords['category']
    myMessage = 'Could not read %s' % myKeywordPath
    assert myKeywords is not None, myMessage

    # Create QGis Layer Instance
    if myExt in ['.asc', '.tif']:
        myLayer = QgsRasterLayer(myPath, myBaseName)
    elif myExt in ['.shp']:
        myLayer = QgsVectorLayer(myPath, myBaseName, 'ogr')
    else:
        myMessage = 'File %s had illegal extension' % myPath
        raise Exception(myMessage)

    myMessage = 'Layer "%s" is not valid' % str(myLayer.source())
    assert myLayer.isValid(), myMessage
    return myLayer, myCategory
示例#18
0
def load_layer(layer_file, directory=TESTDATA):
    """Helper to load and return a single QGIS layer

    :param layer_file: Path name to raster or vector file.
    :type layer_file: str
    :param directory: Optional parent dir. If None, path name is assumed
        to be absolute.
    :type directory: str, None

    :returns: tuple containing layer and its category.
    :rtype: (QgsMapLayer, str)

    """

    # Extract basename and absolute path
    myFilename = os.path.split(layer_file)[-1]  # In case path was absolute
    myBaseName, myExt = os.path.splitext(myFilename)
    if directory is None:
        myPath = layer_file
    else:
        myPath = os.path.join(directory, layer_file)
    myKeywordPath = myPath[:-4] + '.keywords'

    # Determine if layer is hazard or exposure
    myKeywords = readKeywordsFromFile(myKeywordPath)
    myCategory = 'undefined'
    if 'category' in myKeywords:
        myCategory = myKeywords['category']
    myMessage = 'Could not read %s' % myKeywordPath
    assert myKeywords is not None, myMessage

    # Create QGis Layer Instance
    if myExt in ['.asc', '.tif']:
        myLayer = QgsRasterLayer(myPath, myBaseName)
    elif myExt in ['.shp']:
        myLayer = QgsVectorLayer(myPath, myBaseName, 'ogr')
    else:
        myMessage = 'File %s had illegal extension' % myPath
        raise Exception(myMessage)

    myMessage = 'Layer "%s" is not valid' % str(myLayer.source())
    assert myLayer.isValid(), myMessage
    return myLayer, myCategory
示例#19
0
def makePadangLayerClone():
    """Helper function that copies padang keyword for testing and return it."""
    mySourceFileName = 'Shakemap_Padang_2009'
    myExts = [
        '.asc', '.asc.aux.xml', '.keywords', '.lic', '.prj', '.qml', '.sld'
    ]
    myFileName = unique_filename()
    # copy to temp file
    for ext in myExts:
        mySourcePath = os.path.join(HAZDATA, mySourceFileName + ext)
        myDestPath = os.path.join(HAZDATA, myFileName + ext)
        shutil.copy2(mySourcePath, myDestPath)
    # return a single predefined layer
    myFile = myFileName + '.asc'
    myPath = os.path.join(HAZDATA, myFile)
    myTitle = readKeywordsFromFile(myPath, 'title')
    myLayer = QgsRasterLayer(myPath, myTitle)
    QgsMapLayerRegistry.instance().addMapLayer(myLayer)
    return myLayer, myFileName
示例#20
0
def loadLayer(theLayerFile, theDirectory=TESTDATA):
    """Helper to load and return a single QGIS layer

    Args:
        theLayerFile: Pathname to raster or vector file
        DIR: Optional parameter stating the parent dir. If None,
             pathname is assumed to be absolute

    Returns: QgsMapLayer, str (for layer type)

    """

    # Extract basename and absolute path
    myFilename = os.path.split(theLayerFile)[-1]  # In case path was absolute
    myBaseName, myExt = os.path.splitext(myFilename)
    if theDirectory is None:
        myPath = theLayerFile
    else:
        myPath = os.path.join(theDirectory, theLayerFile)
    myKeywordPath = myPath[:-4] + '.keywords'

    # Determine if layer is hazard or exposure
    myKeywords = readKeywordsFromFile(myKeywordPath)
    myType = 'undefined'
    if 'category' in myKeywords:
        myType = myKeywords['category']
    myMessage = 'Could not read %s' % myKeywordPath
    assert myKeywords is not None, myMessage

    # Create QGis Layer Instance
    if myExt in ['.asc', '.tif']:
        myLayer = QgsRasterLayer(myPath, myBaseName)
    elif myExt in ['.shp']:
        myLayer = QgsVectorLayer(myPath, myBaseName, 'ogr')
    else:
        myMessage = 'File %s had illegal extension' % myPath
        raise Exception(myMessage)

    myMessage = 'Layer "%s" is not valid' % str(myLayer.source())
    assert myLayer.isValid(), myMessage
    return myLayer, myType
        myMessage = 'Got: %s\n\nExpected %s\n\nDB: %s' % (
            myKeyword, myExpectedKeyword, self.rasterShakePath)
        assert myKeyword == 'hazard', myMessage

        # Test we get an exception if keyword is not found
        try:
            myKeyword = readKeywordsFromFile(self.rasterShakePath,
                                             'boguskeyword')
        except KeywordNotFoundException:
            pass  # this is good
        except Exception, e:
            myMessage = ('Request for bogus keyword raised incorrect '
                         'exception type: \n %s') % str(e)
            assert (), myMessage

        myKeywords = readKeywordsFromFile(self.rasterShakePath)

        myExpectedKeywords = {
            'category': 'hazard',
            'subcategory': 'earthquake',
            'unit': 'MMI',
            'title': 'An earthquake in Padang like in 2009'
        }
        myMessage = 'Expected:\n%s\nGot:\n%s' % (myKeywords,
                                                 myExpectedKeywords)
        assert myKeywords == myExpectedKeywords, myMessage

        myKeywords = readKeywordsFromFile(self.rasterPopulationPath)
        assert myKeywords == {
            'category': 'exposure',
            'subcategory': 'population',
示例#22
0
        myMessage = 'Got: %s\n\nExpected %s\n\nDB: %s' % (
                    myKeyword, myExpectedKeyword, self.rasterShakePath)
        assert myKeyword == 'hazard', myMessage

        # Test we get an exception if keyword is not found
        try:
            _ = readKeywordsFromFile(self.rasterShakePath,
                                     'boguskeyword')
        except KeywordNotFoundError:
            pass  # this is good
        except Exception, e:
            myMessage = ('Request for bogus keyword raised incorrect '
                         'exception type: \n %s') % str(e)
            assert(), myMessage

        myKeywords = readKeywordsFromFile(self.rasterShakePath)

        myExpectedKeywords = {'category': 'hazard',
                              'subcategory': 'earthquake',
                              'source': 'USGS',
                              'unit': 'MMI',
                              'title': 'An earthquake in Padang like in 2009'}
        myMessage = 'Expected:\n%s\nGot:\n%s\n' % (myExpectedKeywords,
                                                   myKeywords)
        assert myKeywords == myExpectedKeywords, myMessage

        myKeywords = readKeywordsFromFile(self.rasterPopulationPath)
        myExpectedKeywords = {'category': 'exposure',
                              'source': ('Center for International Earth '
                                         'Science Information Network '
                                         '(CIESIN)'),
示例#23
0
def _clip_raster_layer(
        theLayer, theExtent, theCellSize=None, theExtraKeywords=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 theLayer: A valid QGIS raster layer in EPSG:4326
    :type theLayer: QgsRasterLayer

    :param theExtent:  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 theExtent: list(float), QgsGeometry

    :param theCellSize: 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 theCellSize: 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 theLayer or not theExtent:
        myMessage = tr('Layer or Extent passed to clip is None.')
        raise InvalidParameterError(myMessage)

    if theLayer.type() != QgsMapLayer.RasterLayer:
        myMessage = tr(
            'Expected a raster layer but received a %s.' %
            str(theLayer.type()))
        raise InvalidParameterError(myMessage)

    myWorkingLayer = str(theLayer.source())

    # Check for existence of keywords file
    myKeywordsPath = myWorkingLayer[:-4] + '.keywords'
    myMessage = tr(
        'Input file to be clipped "%s" does not have the '
        'expected keywords file %s' % (
            myWorkingLayer, myKeywordsPath))
    verify(os.path.isfile(myKeywordsPath), myMessage)

    # 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.
    myKeywords = readKeywordsFromFile(myKeywordsPath)
    if 'datatype' in myKeywords and myKeywords['datatype'] == 'density':
        if str(theLayer.crs().authid()) != 'EPSG:4326':

            # This layer is not WGS84 geographic
            myMessage = ('Layer %s represents density but has spatial '
                         'reference "%s". Density 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'
                         % (myWorkingLayer, theLayer.crs().toProj4()))
            raise InvalidProjectionError(myMessage)

    # We need to provide gdalwarp with a dataset for the clip
    # because unline gdal_translate, it does not take projwin.
    myClipKml = extent_to_kml(theExtent)

    # Create a filename for the clipped, resampled and reprojected layer
    myHandle, myFilename = tempfile.mkstemp('.tif', 'clip_',
                                            temp_dir())
    os.close(myHandle)
    os.remove(myFilename)

    # If no cell size is specified, we need to run gdalwarp without
    # specifying the output pixel size to ensure the raster dims
    # remain consistent.
    myBinaryList = which('gdalwarp')
    LOGGER.debug('Path for gdalwarp: %s' % myBinaryList)
    if len(myBinaryList) < 1:
        raise CallGDALError(
            tr('gdalwarp could not be found on your computer'))
    # Use the first matching gdalwarp found
    myBinary = myBinaryList[0]
    if theCellSize is None:
        myCommand = ('%s -q -t_srs EPSG:4326 -r near '
                     '-cutline %s -crop_to_cutline -of GTiff '
                     '"%s" "%s"' % (myBinary,
                                    myClipKml,
                                    myWorkingLayer,
                                    myFilename))
    else:
        myCommand = ('%s -q -t_srs EPSG:4326 -r near -tr %f %f '
                     '-cutline %s -crop_to_cutline -of GTiff '
                     '"%s" "%s"' % (myBinary,
                                    theCellSize,
                                    theCellSize,
                                    myClipKml,
                                    myWorkingLayer,
                                    myFilename))

    LOGGER.debug(myCommand)
    myResult = QProcess().execute(myCommand)

    # For QProcess exit codes see
    # http://qt-project.org/doc/qt-4.8/qprocess.html#execute
    if myResult == -2:  # cannot be started
        myMessageDetail = tr('Process could not be started.')
        myMessage = tr(
            '<p>Error while executing the following shell command:'
            '</p><pre>%s</pre><p>Error message: %s'
            % (myCommand, myMessageDetail))
        raise CallGDALError(myMessage)
    elif myResult == -1:  # process crashed
        myMessageDetail = tr('Process could not be started.')
        myMessage = tr('<p>Error while executing the following shell command:'
                       '</p><pre>%s</pre><p>Error message: %s'
                       % (myCommand, myMessageDetail))
        raise CallGDALError(myMessage)

    # .. todo:: Check the result of the shell call is ok
    myKeywordIO = KeywordIO()
    myKeywordIO.copy_keywords(
        theLayer, myFilename, extra_keywords=theExtraKeywords)
    myBaseName = '%s clipped' % theLayer.name()
    myLayer = QgsRasterLayer(myFilename, myBaseName)

    return myLayer
示例#24
0
文件: clipper.py 项目: simod/inasafe
def _clipRasterLayer(theLayer, theExtent, theCellSize=None,
                     theExtraKeywords=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.

    Args:

        * theLayer - a valid QGIS raster layer in EPSG:4326
        * theExtent -  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.
        * theCellSize - 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.

    Returns:
        Path to the output clipped layer (placed in the
        system temp dir).

    Raises:
       Exception if input layer is a density layer in projected coordinates -
       see issue #123

    """
    if not theLayer or not theExtent:
        myMessage = tr('Layer or Extent passed to clip is None.')
        raise InvalidParameterException(myMessage)

    if theLayer.type() != QgsMapLayer.RasterLayer:
        myMessage = tr('Expected a raster layer but received a %s.' %
               str(theLayer.type()))
        raise InvalidParameterException(myMessage)

    myWorkingLayer = str(theLayer.source())

    # Check for existence of keywords file
    myKeywordsPath = myWorkingLayer[:-4] + '.keywords'
    myMessage = tr('Input file to be clipped "%s" does not have the '
           'expected keywords file %s' % (myWorkingLayer,
                                          myKeywordsPath))
    verify(os.path.isfile(myKeywordsPath), myMessage)

    # 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.
    myKeywords = readKeywordsFromFile(myKeywordsPath)
    if 'datatype' in myKeywords and myKeywords['datatype'] == 'density':
        if theLayer.srs().epsg() != 4326:

            # This layer is not WGS84 geographic
            myMessage = ('Layer %s represents density but has spatial '
                         'reference "%s". Density 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'
                         % (myWorkingLayer, theLayer.srs().toProj4()))
            raise InvalidProjectionException(myMessage)

    # We need to provide gdalwarp with a dataset for the clip
    # because unline gdal_translate, it does not take projwin.
    myClipKml = extentToKml(theExtent)

    # Create a filename for the clipped, resampled and reprojected layer
    myHandle, myFilename = tempfile.mkstemp('.tif', 'clip_',
                                            temp_dir())
    os.close(myHandle)
    os.remove(myFilename)

    # If no cell size is specified, we need to run gdalwarp without
    # specifying the output pixel size to ensure the raster dims
    # remain consistent.
    if theCellSize is None:
        myCommand = ('gdalwarp -q -t_srs EPSG:4326 -r near '
                     '-cutline %s -crop_to_cutline -of GTiff '
                     '"%s" "%s"' % (myClipKml,
                                    myWorkingLayer,
                                    myFilename))
    else:
        myCommand = ('gdalwarp -q -t_srs EPSG:4326 -r near -tr %f %f '
                     '-cutline %s -crop_to_cutline -of GTiff '
                     '"%s" "%s"' % (theCellSize,
                                    theCellSize,
                                    myClipKml,
                                    myWorkingLayer,
                                    myFilename))
    myExecutablePrefix = ''
    if sys.platform == 'darwin':  # Mac OS X
        # .. todo:: FIXME - softcode gdal version in this path
        myExecutablePrefix = ('/Library/Frameworks/GDAL.framework/'
                              'Versions/1.9/Programs/')
    myCommand = myExecutablePrefix + myCommand

    LOGGER.debug(myCommand)
    myResult = QProcess().execute(myCommand)

    # For QProcess exit codes see
    # http://qt-project.org/doc/qt-4.8/qprocess.html#execute
    if myResult == -2:  # cannot be started
        myMessageDetail = tr('Process could not be started.')
        myMessage = tr('<p>Error while executing the following shell command:'
                     '</p><pre>%s</pre><p>Error message: %s'
                     % (myCommand, myMessageDetail))
        raise CallGDALError(myMessage)
    elif myResult == -1:  # process crashed
        myMessageDetail = tr('Process could not be started.')
        myMessage = tr('<p>Error while executing the following shell command:'
                       '</p><pre>%s</pre><p>Error message: %s'
                       % (myCommand, myMessageDetail))
        raise CallGDALError(myMessage)

    # .. todo:: Check the result of the shell call is ok
    myKeywordIO = KeywordIO()
    myKeywordIO.copyKeywords(theLayer, myFilename,
                             theExtraKeywords=theExtraKeywords)
    return myFilename  # Filename of created file
示例#25
0
文件: clipper.py 项目: maning/inasafe
def _clipRasterLayer(theLayer,
                     theExtent,
                     theCellSize=None,
                     theExtraKeywords=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.

    Args:

        * theLayer - a valid QGIS raster layer in EPSG:4326
        * theExtent either: 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 is
           currently only supported for vector datasets.**
        * theCellSize - 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.

    Returns:
        Path to the output clipped layer (placed in the
        system temp dir).

    Raises:
       Exception if input layer is a density layer in projected coordinates -
       see issue #123

    """
    if not theLayer or not theExtent:
        myMessage = tr('Layer or Extent passed to clip is None.')
        raise InvalidParameterError(myMessage)

    if theLayer.type() != QgsMapLayer.RasterLayer:
        myMessage = tr('Expected a raster layer but received a %s.' %
                       str(theLayer.type()))
        raise InvalidParameterError(myMessage)

    myWorkingLayer = str(theLayer.source())

    # Check for existence of keywords file
    myKeywordsPath = myWorkingLayer[:-4] + '.keywords'
    myMessage = tr('Input file to be clipped "%s" does not have the '
                   'expected keywords file %s' %
                   (myWorkingLayer, myKeywordsPath))
    verify(os.path.isfile(myKeywordsPath), myMessage)

    # 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.
    myKeywords = readKeywordsFromFile(myKeywordsPath)
    if 'datatype' in myKeywords and myKeywords['datatype'] == 'density':
        if str(theLayer.crs().authid()) != 'EPSG:4326':

            # This layer is not WGS84 geographic
            myMessage = ('Layer %s represents density but has spatial '
                         'reference "%s". Density 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' %
                         (myWorkingLayer, theLayer.crs().toProj4()))
            raise InvalidProjectionError(myMessage)

    # We need to provide gdalwarp with a dataset for the clip
    # because unline gdal_translate, it does not take projwin.
    myClipKml = extentToKml(theExtent)

    # Create a filename for the clipped, resampled and reprojected layer
    myHandle, myFilename = tempfile.mkstemp('.tif', 'clip_', temp_dir())
    os.close(myHandle)
    os.remove(myFilename)

    # If no cell size is specified, we need to run gdalwarp without
    # specifying the output pixel size to ensure the raster dims
    # remain consistent.
    myBinaryList = which('gdalwarp')
    LOGGER.debug('Path for gdalwarp: %s' % myBinaryList)
    if len(myBinaryList) < 1:
        raise CallGDALError(tr('gdalwarp could not be found on your computer'))
    # Use the first matching gdalwarp found
    myBinary = myBinaryList[0]
    if theCellSize is None:
        myCommand = ('%s -q -t_srs EPSG:4326 -r near '
                     '-cutline %s -crop_to_cutline -of GTiff '
                     '"%s" "%s"' %
                     (myBinary, myClipKml, myWorkingLayer, myFilename))
    else:
        myCommand = ('%s -q -t_srs EPSG:4326 -r near -tr %f %f '
                     '-cutline %s -crop_to_cutline -of GTiff '
                     '"%s" "%s"' % (myBinary, theCellSize, theCellSize,
                                    myClipKml, myWorkingLayer, myFilename))

    LOGGER.debug(myCommand)
    myResult = QProcess().execute(myCommand)

    # For QProcess exit codes see
    # http://qt-project.org/doc/qt-4.8/qprocess.html#execute
    if myResult == -2:  # cannot be started
        myMessageDetail = tr('Process could not be started.')
        myMessage = tr('<p>Error while executing the following shell command:'
                       '</p><pre>%s</pre><p>Error message: %s' %
                       (myCommand, myMessageDetail))
        raise CallGDALError(myMessage)
    elif myResult == -1:  # process crashed
        myMessageDetail = tr('Process could not be started.')
        myMessage = tr('<p>Error while executing the following shell command:'
                       '</p><pre>%s</pre><p>Error message: %s' %
                       (myCommand, myMessageDetail))
        raise CallGDALError(myMessage)

    # .. todo:: Check the result of the shell call is ok
    myKeywordIO = KeywordIO()
    myKeywordIO.copyKeywords(theLayer,
                             myFilename,
                             theExtraKeywords=theExtraKeywords)
    return myFilename  # Filename of created file
示例#26
0
def _clipRasterLayer(theLayer,
                     theExtent,
                     theCellSize=None,
                     theExtraKeywords=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.

    Args:

        * theLayer - a valid QGIS raster layer in EPSG:4326
        * theExtent -  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.
        * theCellSize - 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.

    Returns:
        Path to the output clipped layer (placed in the
        system temp dir).

    Raises:
       Exception if input layer is a density layer in projected coordinates -
       see issue #123

    """
    if not theLayer or not theExtent:
        myMessage = tr('Layer or Extent passed to clip is None.')
        raise InvalidParameterException(myMessage)

    if theLayer.type() != QgsMapLayer.RasterLayer:
        myMessage = tr('Expected a raster layer but received a %s.' %
                       str(theLayer.type()))
        raise InvalidParameterException(myMessage)

    myWorkingLayer = str(theLayer.source())

    # Check for existence of keywords file
    myKeywordsPath = myWorkingLayer[:-4] + '.keywords'
    myMessage = tr('Input file to be clipped "%s" does not have the '
                   'expected keywords file %s' %
                   (myWorkingLayer, myKeywordsPath))
    verify(os.path.isfile(myKeywordsPath), myMessage)

    # 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.
    myKeywords = readKeywordsFromFile(myKeywordsPath)
    if 'datatype' in myKeywords and myKeywords['datatype'] == 'density':
        if theLayer.srs().epsg() != 4326:

            # This layer is not WGS84 geographic
            myMessage = ('Layer %s represents density but has spatial '
                         'reference "%s". Density 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' %
                         (myWorkingLayer, theLayer.srs().toProj4()))
            raise InvalidProjectionException(myMessage)

    # We need to provide gdalwarp with a dataset for the clip
    # because unline gdal_translate, it does not take projwin.
    myClipKml = extentToKml(theExtent)

    # Create a filename for the clipped, resampled and reprojected layer
    myHandle, myFilename = tempfile.mkstemp('.tif', 'clip_', temp_dir())
    os.close(myHandle)
    os.remove(myFilename)

    # If no cell size is specified, we need to run gdalwarp without
    # specifying the output pixel size to ensure the raster dims
    # remain consistent.
    if theCellSize is None:
        myCommand = ('gdalwarp -q -t_srs EPSG:4326 -r near '
                     '-cutline %s -crop_to_cutline -of GTiff '
                     '"%s" "%s"' % (myClipKml, myWorkingLayer, myFilename))
    else:
        myCommand = (
            'gdalwarp -q -t_srs EPSG:4326 -r near -tr %f %f '
            '-cutline %s -crop_to_cutline -of GTiff '
            '"%s" "%s"' %
            (theCellSize, theCellSize, myClipKml, myWorkingLayer, myFilename))
    myExecutablePrefix = ''
    if sys.platform == 'darwin':  # Mac OS X
        # .. todo:: FIXME - softcode gdal version in this path
        myExecutablePrefix = ('/Library/Frameworks/GDAL.framework/'
                              'Versions/1.9/Programs/')
    myCommand = myExecutablePrefix + myCommand

    # For debugging only
    # myCommand = myExecutablePrefix + myCommand
    # myFile = file('C:/temp/command.txt', 'wt')
    # myFile.write(myCommand)
    # myFile.close()
    # Now run GDAL warp scottie...
    LOGGER.debug(myCommand)
    try:
        myResult = call(myCommand, shell=True)
        del myResult
    except CalledProcessError, e:
        myMessage = tr('<p>Error while executing the following shell command:'
                       '</p><pre>%s</pre><p>Error message: %s' %
                       (myCommand, str(e)))
        # shameless hack - see https://github.com/AIFDR/inasafe/issues/141
        if sys.platform == 'darwin':  # Mac OS X
            if 'Errno 4' in str(e):
                # continue as the error seems to be non critical
                pass
            else:
                raise Exception(myMessage)
        else:
            raise Exception(myMessage)