def test_availableFunctions(self): """Check we can get the available functions from the impact calculator. """ myList = availableFunctions() assert myList > 1 # 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) myList = [myKeywords1, myKeywords2] myList = availableFunctions(myList) assert myList > 1
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 Exception: raise
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
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: 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
def loadLayer(theLayerFile, DIR=TESTDATA): """Helper to load and return a single QGIS layer Input theLayerFile: Pathname to raster or vector file DIR: Optional parameter stating the parent dir. If None, pathname is assumed to be absolute """ # Extract basename and absolute path myFilename = os.path.split(theLayerFile)[-1] # In case path was absolute myBaseName, myExt = os.path.splitext(myFilename) if DIR is None: myPath = theLayerFile else: myPath = os.path.join(DIR, 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', 'datatype': 'density', 'title': 'People'}
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_', getTempDir()) 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 # Now run GDAL warp scottie... 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)