"""
InaSAFE Disaster risk assessment tool developed by AusAid -
**SAFE Interface test suite.**
Contact : ole.moller.nielsen@gmail.com
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'tim@linfiniti.com'
__date__ = '04/04/2012'
__copyright__ = ('Copyright 2012, Australia Indonesia Facility for '
'Disaster Reduction')
import os
import numpy
import unittest
from safe_qgis.safe_interface import (getOptimalExtent,
availableFunctions,
readKeywordsFromFile,
readSafeLayer)
from safe_qgis.exceptions import (KeywordNotFoundException,
InsufficientOverlapException)
from safe.common.exceptions import BoundingBoxError
from safe.common.testing import TESTDATA, HAZDATA, EXPDATA
[docs]class SafeInterfaceTest(unittest.TestCase):
"""Test the SAFE API Wrapper"""
[docs] def setUp(self):
"""Setup test before each unit"""
self.vectorPath = os.path.join(TESTDATA, 'Padang_WGS84.shp')
self.rasterShakePath = os.path.join(HAZDATA,
'Shakemap_Padang_2009.asc')
self.rasterTsunamiPath = os.path.join(TESTDATA,
'tsunami_max_inundation_depth_utm56s.tif')
self.rasterExposurePath = os.path.join(TESTDATA,
'tsunami_building_exposure.shp')
self.rasterPopulationPath = os.path.join(EXPDATA, 'glp10ag.asc')
[docs] def test_getOptimalExtent(self):
"""Optimal extent is calculated correctly
"""
exposure_path = os.path.join(TESTDATA, 'Population_2010.asc')
hazard_path = os.path.join(HAZDATA,
'Lembang_Earthquake_Scenario.asc')
# Expected data
haz_metadata = {'bounding_box': (105.3000035,
-8.3749994999999995,
110.2914705,
-5.5667784999999999),
'resolution': (0.0083330000000000001,
0.0083330000000000001)}
exp_metadata = {'bounding_box': (94.972335000000001,
-11.009721000000001,
141.0140016666665,
6.0736123333332639),
'resolution': (0.0083333333333333003,
0.0083333333333333003)}
# Verify relevant metada is ok
H = readSafeLayer(hazard_path)
E = readSafeLayer(exposure_path)
hazard_bbox = H.get_bounding_box()
assert numpy.allclose(hazard_bbox, haz_metadata['bounding_box'],
rtol=1.0e-12, atol=1.0e-12)
exposure_bbox = E.get_bounding_box()
assert numpy.allclose(exposure_bbox, exp_metadata['bounding_box'],
rtol=1.0e-12, atol=1.0e-12)
hazard_res = H.get_resolution()
assert numpy.allclose(hazard_res, haz_metadata['resolution'],
rtol=1.0e-12, atol=1.0e-12)
exposure_res = E.get_resolution()
assert numpy.allclose(exposure_res, exp_metadata['resolution'],
rtol=1.0e-12, atol=1.0e-12)
# First, do some examples that produce valid results
ref_box = [105.3000035, -8.3749995, 110.2914705, -5.5667785]
view_port = [94.972335, -11.009721, 141.014002, 6.073612]
bbox = getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12)
#testing with viewport clipping disabled
bbox = getOptimalExtent(hazard_bbox, exposure_bbox, None)
assert numpy.allclose(bbox, ref_box, rtol=1.0e-12, atol=1.0e-12)
view_port = [105.3000035,
-8.3749994999999995,
110.2914705,
-5.5667784999999999]
bbox = getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
assert numpy.allclose(bbox, ref_box,
rtol=1.0e-12, atol=1.0e-12)
# Very small viewport fully inside other layers
view_port = [106.0, -6.0, 108.0, -5.8]
bbox = getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
assert numpy.allclose(bbox, view_port,
rtol=1.0e-12, atol=1.0e-12)
# viewport that intersects hazard layer
view_port = [107.0, -6.0, 112.0, -3.0]
ref_box = [107, -6, 110.2914705, -5.5667785]
bbox = getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
assert numpy.allclose(bbox, ref_box,
rtol=1.0e-12, atol=1.0e-12)
# Then one where boxes don't overlap
view_port = [105.3, -4.3, 110.29, -2.5]
try:
getOptimalExtent(hazard_bbox, exposure_bbox, view_port)
except InsufficientOverlapException, e:
myMessage = 'Did not find expected error message in %s' % str(e)
assert 'did not overlap' in str(e), myMessage
else:
myMessage = ('Non ovelapping bounding boxes should have raised '
'an exception')
raise Exception(myMessage)
# Try with wrong input data
try:
getOptimalExtent(haz_metadata, exp_metadata, view_port)
except BoundingBoxError:
#good this was expected
pass
except InsufficientOverlapException, e:
myMessage = 'Did not find expected error message in %s' % str(e)
assert 'Invalid' in str(e), myMessage
else:
myMessage = ('Wrong input data should have raised an exception')
raise Exception(myMessage)
try:
getOptimalExtent(None, None, view_port)
except BoundingBoxError, e:
myMessage = 'Did not find expected error message in %s' % str(e)
assert 'cannot be None' in str(e), myMessage
else:
myMessage = ('Wrong input data should have raised an exception')
raise Exception(myMessage)
try:
getOptimalExtent('aoeush', 'oeuuoe', view_port)
except BoundingBoxError, e:
myMessage = 'Did not find expected error message in %s' % str(e)
assert 'Instead i got "aoeush"' in str(e), myMessage
else:
myMessage = ('Wrong input data should have raised an exception')
raise Exception(myMessage)
[docs] 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
[docs] 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
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)'),
'subcategory': 'population',
'datatype': 'density',
'title': 'People'}
myMessage = 'Expected:\n%s\nGot:\n%s\n' % (myExpectedKeywords,
myKeywords)
assert myKeywords == myExpectedKeywords, myMessage
myKeywords = readKeywordsFromFile(self.vectorPath)
myExpectedKeywords = {'category': 'exposure',
'datatype': 'itb',
'subcategory': 'structure'}
myMessage = 'Expected:\n%s\nGot:\n%s\n' % (myExpectedKeywords,
myKeywords)
assert myKeywords == myExpectedKeywords, myMessage
# tsunami example (one layer is UTM)
myKeywords = readKeywordsFromFile(self.rasterTsunamiPath)
myExpectedKeywords = {'title': 'Tsunami Max Inundation',
'category': 'hazard',
'subcategory': 'tsunami',
'unit': 'm'}
myMessage = 'Expected:\n%s\nGot:\n%s\n' % (myExpectedKeywords,
myKeywords)
assert myKeywords == myExpectedKeywords, myMessage
myKeywords = readKeywordsFromFile(self.rasterExposurePath)
myExpectedKeywords = {'category': 'exposure',
'subcategory': 'structure',
'title': 'Tsunami Building Exposure'}
myMessage = 'Expected:\n%s\nGot:\n%s\n' % (myExpectedKeywords,
myKeywords)
assert myKeywords == myExpectedKeywords, myMessage
if __name__ == '__main__':
suite = unittest.makeSuite(SafeInterfaceTest, 'test')
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)