示例#1
0
 def test_list(self):
     """TestRegistry: Test list all register IFs."""
     registry = Registry()
     impact_functions = registry.list()
     expected = [
         'Polygon flood on buildings',
         'Polygon flood on roads',
         'Polygon flood on people',
         'Raster flood on population',
         'Raster flood on buildings',
         'Raster flood on roads (QGIS)',
         'Raster flood on roads (GDAL)',
         'Tsunami evacuation',
         'Classified raster hazard on buildings',
         'Classified raster hazard on population',
         'Continuous raster hazard on population',
         'Classified polygon hazard on population',
         'Classified polygon hazard on buildings',
         'Earthquake on buildings',
         'Earthquake ITB fatality function',
         'Earthquake PAGER fatality function',
         'Point volcano on buildings',
         'Polygon volcano on buildings',
         'Point volcano on population',
         'Polygon volcano on population']
     self.assertTrue(len(impact_functions) == len(expected))
     self.assertItemsEqual(expected, impact_functions)
示例#2
0
    def test_filter_by_keywords_dev(self):
        """TestRegistry: Test filtering IF using hazard n exposure keywords.

        Note (IS): I use this test to check the result of IF filtering only.
        """
        registry = Registry()

        # Using keywords string
        hazard_keywords = {
            'continuous_hazard_unit': 'metres',
            'hazard': 'flood',
            'hazard_category': 'single_event',
            'layer_mode': 'continuous',
            'layer_purpose': 'hazard',
            'title': 'Jakarta flood like 2007 with structural improvements'
        }
        exposure_keywords = {
            'exposure': 'population',
            'exposure_unit': 'count',
            'layer_geometry': 'raster',
            'layer_mode': 'continuous',
            'layer_purpose': 'exposure',
            'title': 'Population'
        }

        impact_functions = registry.filter_by_keyword_string(
            hazard_keywords, exposure_keywords)

        # print len(impact_functions)

        for i in impact_functions:
            # print i.__name__
            continue
示例#3
0
 def test_list(self):
     """TestRegistry: Test list all register IFs."""
     registry = Registry()
     impact_functions = registry.list()
     expected = [
         'Polygon flood on buildings',
         'Polygon flood on roads',
         'Polygon flood on people',
         'Raster flood on population',
         'Raster flood on buildings',
         'Raster flood on roads (QGIS)',
         'Raster flood on roads (GDAL)',
         'Tsunami evacuation',
         'Classified raster hazard on buildings',
         'Classified raster hazard on population',
         'Continuous raster hazard on population',
         'Classified polygon hazard on population',
         'Classified polygon hazard on buildings',
         'Earthquake on buildings',
         'Earthquake ITB fatality function',
         'Earthquake PAGER fatality function',
         'Point volcano on buildings',
         'Polygon volcano on buildings',
         'Point volcano on population',
         'Polygon volcano on population']
     self.assertTrue(len(impact_functions) == len(expected))
     self.assertItemsEqual(expected, impact_functions)
示例#4
0
    def test_filter_by_keywords_dev(self):
        """TestRegistry: Test filtering IF using hazard n exposure keywords.

        Note (IS): I use this test to check the result of IF filtering only.
        """
        registry = Registry()

        # Using keywords string
        hazard_keywords = {
            'continuous_hazard_unit': 'metres',
            'hazard': 'flood',
            'hazard_category': 'single_event',
            'layer_mode': 'continuous',
            'layer_purpose': 'hazard',
            'title': 'Jakarta flood like 2007 with structural improvements'
        }
        exposure_keywords = {
            'exposure': 'population',
            'exposure_unit': 'count',
            'layer_geometry': 'raster',
            'layer_mode': 'continuous',
            'layer_purpose': 'exposure',
            'title': 'Population'
        }

        impact_functions = registry.filter_by_keyword_string(
            hazard_keywords, exposure_keywords)

        print len(impact_functions)

        for i in impact_functions:
            print i.__name__
示例#5
0
 def test_get_impact_function_instance(self):
     """TestRegistry: Test we can get an impact function instance."""
     # Getting an IF instance using its class name
     registry = Registry()
     class_name = 'FloodPolygonBuildingFunction'
     impact_function = registry.get_instance(class_name)
     result = impact_function.__class__.__name__
     message = 'Expecting FloodPolygonBuildingFunction. Got %s ' \
               'instead.' % result
     self.assertEqual(class_name, result, message)
示例#6
0
 def test_get_impact_function_instance(self):
     """TestRegistry: Test we can get an impact function instance."""
     # Getting an IF instance using its class name
     registry = Registry()
     class_name = 'FloodPolygonBuildingFunction'
     impact_function = registry.get_instance(class_name)
     result = impact_function.__class__.__name__
     message = 'Expecting FloodPolygonBuildingFunction. Got %s ' \
               'instead.' % result
     self.assertEqual(class_name, result, message)
示例#7
0
    def test_filter_by_keywords(self):
        """TestRegistry: Test filtering IF using hazard n exposure keywords."""
        registry = Registry()
        impact_functions = registry.filter_by_keyword_string()
        message = 'Registry should returns matched impact functions. ' \
                  'Nothing returned instead. Please check registered IF.'
        self.assertTrue(len(impact_functions) > 0, message)

        # Using keywords string
        hazard_keywords = {
            'layer_purpose': 'hazard',
            'layer_mode': 'classified',
            'layer_geometry': 'polygon',
            'hazard': 'flood',
            'hazard_category': 'single_event',
            'vector_hazard_classification': 'flood_vector_hazard_classes'
        }

        exposure_keywords = {
            'layer_purpose': 'exposure',
            'layer_mode': 'classified',
            'layer_geometry': 'polygon',
            'exposure': 'structure',
        }

        impact_functions = registry.filter_by_keyword_string(
            hazard_keywords, exposure_keywords)
        message = 'Registry should returns matched impact functions. ' \
                  'Nothing returned instead. Please check registered IF.'
        self.assertTrue(len(impact_functions) > 0, message)

        for i in impact_functions:
            # print i.__name__
            continue

        for impact_function in impact_functions:
            result = impact_function.metadata().as_dict()[
                'layer_requirements']['hazard']['hazard_types']
            result_list = [subcat.get('key') for subcat in result]
            expected = 'flood'
            message = 'Expecting flood hazard impact functions. Got %s ' \
                      'instead' % result_list[0]
            self.assertTrue(expected in result_list, message)

            result = impact_function.metadata().as_dict()[
                'layer_requirements']['exposure']['exposure_types']
            result_list = [subcat.get('key') for subcat in result]
            expected = 'structure'
            message = 'Expecting structure exposure impact functions. ' \
                      'Got %s instead' % result_list[0]
            self.assertTrue(expected in result_list, message)
    def test_filter_by_exposure_metadata(self):
        """TestRegistry: Test filtering IF by exposure metadata."""
        # Full metadata
        exposure_metadata = {
            'layer_mode': layer_mode_classified,
            'layer_geometry': layer_geometry_point,
            'exposure': exposure_structure,
            'exposure_unit': []
            }
        registry = Registry()
        impact_functions = registry.filter_by_exposure(
            registry.impact_functions, exposure_metadata)
        expected = [
            FloodPolygonBuildingFunction,
            FloodRasterBuildingFunction,
            TsunamiRasterBuildingFunction,
            ClassifiedRasterHazardBuildingFunction,
            ClassifiedPolygonHazardBuildingFunction,
            EarthquakeBuildingFunction,
            VolcanoPointBuildingFunction,
            VolcanoPolygonBuildingFunction
        ]
        message = 'Expecting \n%s.\n\nGot \n%s \n instead' % (
            '\n'.join([x.__name__ for x in expected]),
            '\n'.join([x.__name__ for x in impact_functions]))
        self.assertItemsEqual(expected, impact_functions, message)

        # Full metadata
        exposure_metadata = {
            'layer_mode': layer_mode_classified,
            'layer_geometry': layer_geometry_polygon,
            'exposure': exposure_structure,
            # 'exposure_unit': []
        }
        registry = Registry()
        impact_functions = registry.filter_by_exposure(
            registry.impact_functions, exposure_metadata)
        expected = [
            FloodPolygonBuildingFunction,
            FloodRasterBuildingFunction,
            TsunamiRasterBuildingFunction,
            ClassifiedRasterHazardBuildingFunction,
            ClassifiedPolygonHazardBuildingFunction,
            EarthquakeBuildingFunction,
            VolcanoPointBuildingFunction,
            VolcanoPolygonBuildingFunction,
        ]
        message = 'Expecting \n%s.\n\nGot \n%s instead' % (
            '\n'.join([x.__name__ for x in expected]),
            '\n'.join([x.__name__ for x in impact_functions]))
        self.assertItemsEqual(expected, impact_functions, message)
示例#9
0
    def test_filter_by_keywords(self):
        """TestRegistry: Test filtering IF using hazard n exposure keywords."""
        registry = Registry()
        impact_functions = registry.filter_by_keyword_string()
        message = 'Registry should returns matched impact functions. ' \
                  'Nothing returned instead. Please check registered IF.'
        self.assertTrue(len(impact_functions) > 0, message)

        # Using keywords string
        hazard_keywords = {
            'layer_purpose': 'hazard',
            'layer_mode': 'classified',
            'layer_geometry': 'polygon',
            'hazard': 'flood',
            'hazard_category': 'single_event',
            'vector_hazard_classification': 'flood_vector_hazard_classes'
        }

        exposure_keywords = {
            'layer_purpose': 'exposure',
            'layer_mode': 'classified',
            'layer_geometry': 'polygon',
            'exposure': 'structure',
        }

        impact_functions = registry.filter_by_keyword_string(
            hazard_keywords, exposure_keywords)
        message = 'Registry should returns matched impact functions. ' \
                  'Nothing returned instead. Please check registered IF.'
        self.assertTrue(len(impact_functions) > 0, message)

        for i in impact_functions:
            # print i.__name__
            continue

        for impact_function in impact_functions:
            result = impact_function.metadata().as_dict(
            )['layer_requirements']['hazard']['hazard_types']
            result_list = [subcat.get('key') for subcat in result]
            expected = 'flood'
            message = 'Expecting flood hazard impact functions. Got %s ' \
                      'instead' % result_list[0]
            self.assertTrue(expected in result_list, message)

            result = impact_function.metadata().as_dict(
            )['layer_requirements']['exposure']['exposure_types']
            result_list = [subcat.get('key') for subcat in result]
            expected = 'structure'
            message = 'Expecting structure exposure impact functions. ' \
                      'Got %s instead' % result_list[0]
            self.assertTrue(expected in result_list, message)
示例#10
0
    def test_get_impact_function_class(self):
        """TestRegistry: Test we can get an impact function class."""
        # Getting an IF class using its class name
        registry = Registry()
        expected = 'FloodPolygonBuildingFunction'
        impact_function = registry.get_class(expected)

        # Check that it should be a class, not an instance
        message = 'Expecting a class, not an object'
        self.assertTrue(inspect.isclass(impact_function), message)

        # Check the IF name the same
        result = impact_function.__name__
        message = 'Expecting %s. Got %s instead.' % (expected, result)
        self.assertEqual(expected, result, message)
示例#11
0
    def test_get_impact_function_class(self):
        """TestRegistry: Test we can get an impact function class."""
        # Getting an IF class using its class name
        registry = Registry()
        expected = 'FloodPolygonBuildingFunction'
        impact_function = registry.get_class(expected)

        # Check that it should be a class, not an instance
        message = 'Expecting a class, not an object'
        self.assertTrue(inspect.isclass(impact_function), message)

        # Check the IF name the same
        result = impact_function.__name__
        message = 'Expecting %s. Got %s instead.' % (expected, result)
        self.assertEqual(expected, result, message)
示例#12
0
    def test_get_impact_functions_by_metadata(self):
        """TestRegistry: Test getting the impact functions by its metadata."""
        # Test getting the impact functions by 'id'
        registry = Registry()
        impact_function_id = 'FloodPolygonBuildingFunction'
        result = registry.filter_by_metadata('id', impact_function_id)
        expected = [FloodPolygonBuildingFunction]
        message = 'Expecting %s. Got %s instead' % (expected, result)
        self.assertEqual(expected, result, message)

        # Test getting the impact functions by 'name'
        impact_function_name = 'Polygon flood on buildings'
        result = registry.filter_by_metadata('name', impact_function_name)
        expected = [FloodPolygonBuildingFunction]
        message = 'Expecting %s. Got %s instead.' % (expected, result)
        self.assertEqual(expected, result, message)
示例#13
0
    def test_get_impact_functions_by_metadata(self):
        """TestRegistry: Test getting the impact functions by its metadata."""
        # Test getting the impact functions by 'id'
        registry = Registry()
        impact_function_id = 'FloodPolygonBuildingFunction'
        result = registry.filter_by_metadata('id', impact_function_id)
        expected = [FloodPolygonBuildingFunction]
        message = 'Expecting %s. Got %s instead' % (expected, result)
        self.assertEqual(expected, result, message)

        # Test getting the impact functions by 'name'
        impact_function_name = 'Polygon flood on buildings'
        result = registry.filter_by_metadata('name', impact_function_name)
        expected = [FloodPolygonBuildingFunction]
        message = 'Expecting %s. Got %s instead.' % (expected, result)
        self.assertEqual(expected, result, message)
示例#14
0
    def test_filter_by_metadata(self):
        """TestRegistry: Test filtering IF by hazard and exposure metadata."""
        hazard_metadata = {
            'subcategory': hazard_flood,
            'units': unit_wetdry,
            'layer_constraints': layer_vector_polygon
        }

        exposure_metadata = {
            'subcategory': exposure_structure,
            'units': unit_building_type_type,
            'layer_constraints': layer_vector_polygon
        }

        registry = Registry()
        impact_functions = registry.filter(hazard_metadata, exposure_metadata)
        expected = [FloodPolygonBuildingFunction]
        message = 'Expecting %s. Got %s instead' % (expected, impact_functions)
        self.assertEqual(expected, impact_functions, message)
示例#15
0
    def test_filter_by_metadata(self):
        """TestRegistry: Test filtering IF by hazard and exposure metadata."""
        hazard_metadata = {
            'subcategory': hazard_flood,
            'units': unit_wetdry,
            'layer_constraints': layer_vector_polygon
        }

        exposure_metadata = {
            'subcategory': exposure_structure,
            'units': unit_building_type_type,
            'layer_constraints': layer_vector_polygon
        }

        registry = Registry()
        impact_functions = registry.filter(hazard_metadata, exposure_metadata)
        expected = [FloodPolygonBuildingFunction]
        message = 'Expecting %s. Got %s instead' % (expected, impact_functions)
        self.assertEqual(expected, impact_functions, message)
示例#16
0
    def test_filter_by_hazard_metadata(self):
        """TestRegistry: Test filtering IF by hazard metadata."""
        # Full metadata
        hazard_metadata = {
            'layer_mode': layer_mode_continuous,
            'layer_geometry': layer_geometry_raster,
            'hazard_category': hazard_category_single_event,
            'hazard': hazard_earthquake,
            'continuous_hazard_unit': unit_mmi,
        }
        registry = Registry()
        impact_functions = registry.filter_by_hazard(
            registry.impact_functions, hazard_metadata)
        expected = [
            ITBFatalityFunction,
            EarthquakeBuildingFunction,
            PAGFatalityFunction,
            ITBBayesianFatalityFunction
        ]

        message = 'Expecting \n%s.\n\nGot \n%s instead' % (
            '\n'.join([x.__name__ for x in expected]),
            '\n'.join([x.__name__ for x in impact_functions]))
        self.assertItemsEqual(expected, impact_functions, message)

        # Miss one metadata
        hazard_metadata = {
            'layer_mode': layer_mode_continuous,
            'layer_geometry': layer_geometry_raster,
            'hazard_category': hazard_category_single_event,
            'hazard': hazard_earthquake,
            # 'continuous_hazard_unit': unit_mmi,
            }
        registry = Registry()
        impact_functions = registry.filter_by_hazard(
            registry.impact_functions, hazard_metadata)
        expected = [
            # ITBFatalityFunction,
            # EarthquakeBuildingFunction,
            # PAGFatalityFunction
        ]
        message = 'Expecting %s. Got %s instead' % (expected, impact_functions)
        self.assertItemsEqual(expected, impact_functions, message)
示例#17
0
    def test_filter_by_keywords(self):
        """TestRegistry: Test filtering IF using hazard n exposure keywords."""
        # Using keywords string
        hazard_keywords = {
            'subcategory': 'flood',
            'units': 'wetdry',
            'layer_type': 'vector',
            'data_type': 'polygon'
        }

        exposure_keywords = {
            'subcategory': 'structure',
            'units': 'building_type',
            'layer_type': 'vector',
            'data_type': 'polygon'
        }
        registry = Registry()
        impact_functions = registry.filter_by_keyword_string(
            hazard_keywords, exposure_keywords)
        message = 'Registry should returns matched impact functions. ' \
                  'Nothing returned instead. Please check registered IF.'
        self.assertTrue(len(impact_functions) > 0, message)

        for impact_function in impact_functions:
            result = impact_function.metadata().as_dict()[
                'categories']['hazard']['subcategories']
            result_list = [subcat.get('id') for subcat in result]
            expected = 'flood'
            message = 'Expecting flood hazard impact functions. Got %s ' \
                      'instead' % result_list[0]
            self.assertTrue(expected in result_list, message)

            result = impact_function.metadata().as_dict()[
                'categories']['exposure']['subcategories']
            result_list = [subcat.get('id') for subcat in result]
            expected = 'structure'
            message = 'Expecting structure exposure impact functions. ' \
                      'Got %s instead' % result_list[0]
            self.assertTrue(expected in result_list, message)
示例#18
0
    def test_filter_by_keywords(self):
        """TestRegistry: Test filtering IF using hazard n exposure keywords."""
        # Using keywords string
        hazard_keywords = {
            'subcategory': 'flood',
            'units': 'wetdry',
            'layer_type': 'vector',
            'data_type': 'polygon'
        }

        exposure_keywords = {
            'subcategory': 'structure',
            'units': 'building_type',
            'layer_type': 'vector',
            'data_type': 'polygon'
        }
        registry = Registry()
        impact_functions = registry.filter_by_keyword_string(
            hazard_keywords, exposure_keywords)
        message = 'Registry should returns matched impact functions. ' \
                  'Nothing returned instead. Please check registered IF.'
        self.assertTrue(len(impact_functions) > 0, message)

        for impact_function in impact_functions:
            result = impact_function.metadata().as_dict(
            )['categories']['hazard']['subcategories']
            result_list = [subcat.get('id') for subcat in result]
            expected = 'flood'
            message = 'Expecting flood hazard impact functions. Got %s ' \
                      'instead' % result_list[0]
            self.assertTrue(expected in result_list, message)

            result = impact_function.metadata().as_dict(
            )['categories']['exposure']['subcategories']
            result_list = [subcat.get('id') for subcat in result]
            expected = 'structure'
            message = 'Expecting structure exposure impact functions. ' \
                      'Got %s instead' % result_list[0]
            self.assertTrue(expected in result_list, message)
示例#19
0
    def test_filter_by_metadata(self):
        """TestRegistry: Test filtering IF by hazard and exposure metadata."""
        hazard_metadata = {
            'layer_mode': layer_mode_continuous,
            'layer_geometry': layer_geometry_raster,
            'hazard_category': hazard_category_single_event,
            'hazard': hazard_earthquake,
            'continuous_hazard_unit': unit_mmi
        }

        exposure_metadata = {
            'layer_mode': layer_mode_classified,
            'layer_geometry': layer_geometry_point,
            'exposure': exposure_structure,
        }

        registry = Registry()
        impact_functions = registry.filter(hazard_metadata, exposure_metadata)
        expected = [EarthquakeBuildingFunction]
        message = 'Expecting \n%s.\n\nGot \n%s instead' % ('\n'.join([
            x.__name__ for x in expected
        ]), '\n'.join([x.__name__ for x in impact_functions]))
        self.assertEqual(expected, impact_functions, message)
示例#20
0
    def test_filter_by_metadata(self):
        """TestRegistry: Test filtering IF by hazard and exposure metadata."""
        hazard_metadata = {
            'layer_mode': layer_mode_continuous,
            'layer_geometry': layer_geometry_raster,
            'hazard_category': hazard_category_single_event,
            'hazard': hazard_earthquake,
            'continuous_hazard_unit': unit_mmi
        }

        exposure_metadata = {
            'layer_mode': layer_mode_classified,
            'layer_geometry': layer_geometry_point,
            'exposure': exposure_structure,
        }

        registry = Registry()
        impact_functions = registry.filter(hazard_metadata, exposure_metadata)
        expected = [EarthquakeBuildingFunction]
        message = 'Expecting \n%s.\n\nGot \n%s instead' % (
            '\n'.join([x.__name__ for x in expected]),
            '\n'.join([x.__name__ for x in impact_functions]))
        self.assertEqual(expected, impact_functions, message)
示例#21
0
    def test_filter_by_exposure_metadata(self):
        """TestRegistry: Test filtering IF by exposure metadata."""
        # Full metadata
        exposure_metadata = {
            'layer_mode': layer_mode_classified,
            'layer_geometry': layer_geometry_point,
            'exposure': exposure_structure,
            'exposure_unit': []
            }
        registry = Registry()
        impact_functions = registry.filter_by_exposure(
            registry.impact_functions, exposure_metadata)
        expected = [
            FloodPolygonBuildingFunction,
            FloodRasterBuildingFunction,
            TsunamiRasterBuildingFunction,
            ClassifiedRasterHazardBuildingFunction,
            ClassifiedPolygonHazardBuildingFunction,
            EarthquakeBuildingFunction,
            VolcanoPointBuildingFunction,
            VolcanoPolygonBuildingFunction
        ]
        message = 'Expecting \n%s.\n\nGot \n%s \n instead' % (
            '\n'.join([x.__name__ for x in expected]),
            '\n'.join([x.__name__ for x in impact_functions]))
        self.assertItemsEqual(expected, impact_functions, message)

        # Full metadata
        exposure_metadata = {
            'layer_mode': layer_mode_classified,
            'layer_geometry': layer_geometry_polygon,
            'exposure': exposure_structure,
            # 'exposure_unit': []
        }
        registry = Registry()
        impact_functions = registry.filter_by_exposure(
            registry.impact_functions, exposure_metadata)
        expected = [
            FloodPolygonBuildingFunction,
            FloodRasterBuildingFunction,
            TsunamiRasterBuildingFunction,
            ClassifiedRasterHazardBuildingFunction,
            ClassifiedPolygonHazardBuildingFunction,
            EarthquakeBuildingFunction,
            VolcanoPointBuildingFunction,
            VolcanoPolygonBuildingFunction,
        ]
        message = 'Expecting \n%s.\n\nGot \n%s instead' % (
            '\n'.join([x.__name__ for x in expected]),
            '\n'.join([x.__name__ for x in impact_functions]))
        self.assertItemsEqual(expected, impact_functions, message)
示例#22
0
    def test_register_and_clear(self):
        """TestRegistry: Test register and clear impact function."""
        registry = Registry()
        registry.clear()
        message = 'Expecting registry should be cleared. %s impact ' \
                  'functions exists instead' % len(registry.impact_functions)
        self.assertEqual(0, len(registry.impact_functions), message)

        registry.register(FloodPolygonBuildingFunction)
        message = 'Expecting registry will contains 1 impact functions. %s ' \
                  'impact functions exists' % len(registry.impact_functions)
        self.assertEqual(1, len(registry.impact_functions), message)

        result = registry.get_instance('FloodPolygonBuildingFunction')\
            .metadata().as_dict()['id']
        expected = 'FloodPolygonBuildingFunction'
        message = 'Expected registered impact function ID should be %s. ' \
                  'Got %s instead' % (expected, result)
        self.assertEqual(expected, result, message)
示例#23
0
    def test_register_and_clear(self):
        """TestRegistry: Test register and clear impact function."""
        registry = Registry()
        registry.clear()
        message = 'Expecting registry should be cleared. %s impact ' \
                  'functions exists instead' % len(registry.impact_functions)
        self.assertEqual(0, len(registry.impact_functions), message)

        registry.register(FloodPolygonBuildingFunction)
        message = 'Expecting registry will contains 1 impact functions. %s ' \
                  'impact functions exists' % len(registry.impact_functions)
        self.assertEqual(1, len(registry.impact_functions), message)

        result = registry.get_instance('FloodPolygonBuildingFunction')\
            .metadata().as_dict()['id']
        expected = 'FloodPolygonBuildingFunction'
        message = 'Expected registered impact function ID should be %s. ' \
                  'Got %s instead' % (expected, result)
        self.assertEqual(expected, result, message)
示例#24
0
    def test_filter_by_hazard_metadata(self):
        """TestRegistry: Test filtering IF by hazard metadata."""
        # Full metadata
        hazard_metadata = {
            'layer_mode': layer_mode_continuous,
            'layer_geometry': layer_geometry_raster,
            'hazard_category': hazard_category_single_event,
            'hazard': hazard_earthquake,
            'continuous_hazard_unit': unit_mmi,
        }
        registry = Registry()
        impact_functions = registry.filter_by_hazard(
            registry.impact_functions, hazard_metadata)
        expected = [
            ITBFatalityFunction,
            EarthquakeBuildingFunction,
            PAGFatalityFunction,
            ITBBayesianFatalityFunction
        ]

        message = 'Expecting \n%s.\n\nGot \n%s instead' % (
            '\n'.join([x.__name__ for x in expected]),
            '\n'.join([x.__name__ for x in impact_functions]))
        self.assertItemsEqual(expected, impact_functions, message)

        # Miss one metadata
        hazard_metadata = {
            'layer_mode': layer_mode_continuous,
            'layer_geometry': layer_geometry_raster,
            'hazard_category': hazard_category_single_event,
            'hazard': hazard_earthquake,
            # 'continuous_hazard_unit': unit_mmi,
            }
        registry = Registry()
        impact_functions = registry.filter_by_hazard(
            registry.impact_functions, hazard_metadata)
        expected = [
            # ITBFatalityFunction,
            # EarthquakeBuildingFunction,
            # PAGFatalityFunction
        ]
        message = 'Expecting %s. Got %s instead' % (expected, impact_functions)
        self.assertItemsEqual(expected, impact_functions, message)
 def __init__(self):
     """Constructor."""
     # Singleton Registry to track all the registered Impact Functions
     self.registry = Registry()
示例#26
0
class ImpactFunctionManager(object):
    """Class for managing metadata for all impact function.

    .. versionadded:: 2.1
    """
    def __init__(self):
        """Constructor."""
        # Singleton Registry to track all the registered Impact Functions
        self.registry = Registry()

    @property
    def impact_functions(self):
        """Return all registered impact functions."""
        return self.registry.impact_functions

    def get_instance(self, class_name):
        """Return an instance of an impact function given its class name.

        .. example::

            if_manager = ImpactFunctionManager()
            if_class_name = 'FloodBuildingImpactFunction'
            if =  if_manager.get_instance(if_class_name)

        :param class_name: The name of IF class.
        :type class_name: str

        :return: Impact function instance that matches the argument.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        return self.registry.get_instance(class_name)

    def get_class(self, class_name):
        """Return the class of an impact function given its class name.

        .. example::

            if_manager = ImpactFunctionManager()
            if_class_name = 'FloodBuildingImpactFunction'
            if_class =  if_manager.get_class(if_class_name)

        :param class_name: the name of IF class
        :type class_name: str

        :return: impact function class that matches the argument.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        return self.registry.get_class(class_name)

    def get(self, impact_function_id):
        """Return an instance of an impact function given its ID.

        This is a preferred way to get an instance of IF. IF should have a
        unique human readable ID in their metadata.

        .. example::

            if_manager = ImpactFunctionManager()
            if_id = 'FloodBuildingImpactFunction'
            if =  if_manager.get(if_id)

        :param impact_function_id: The ID of impact function in the metadata.
        :type impact_function_id: str

        :return An Impact function instance that has matched id.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        impact_functions = self.registry.filter_by_metadata(
            'id', impact_function_id)
        if len(impact_functions) == 0:
            raise Exception('Impact function with ID: %s not found' %
                            impact_function_id)
        elif len(impact_functions) > 1:
            raise Exception(
                'There are some Impact Functions that have the same ID: %s' %
                impact_function_id)
        return impact_functions[0].instance()

    def filter(self, hazard_metadata=None, exposure_metadata=None):
        """Get available impact functions from hazard and exposure metadata.

        Disabled impact function will not be loaded.

        .. example::

            if_manager = ImpactFunctionManager()
            hazard_metadata = {
                'subcategory': hazard_flood,
                'units': unit_wetdry,
                'layer_constraints': layer_vector_polygon
            }
            exposure_metadata = {
                'subcategory': exposure_structure,
                'units': unit_building_type_type,
                'layer_constraints': layer_vector_polygon
            }
            ifs =  if_manager.filter(hazard_metadata, exposure_metadata)

        :param hazard_metadata: The metadata of the hazard.
        :type hazard_metadata: dict

        :param exposure_metadata: The metadata of the exposure.
        :type exposure_metadata: dict
        """
        return self.registry.filter(hazard_metadata, exposure_metadata)

    def filter_by_keywords(self, hazard_keywords=None, exposure_keywords=None):
        """Get available impact functions from hazard and exposure keywords.

        Disabled impact function will not be loaded.

        .. example::

            if_manager = ImpactFunctionManager()
            hazard_keywords = {
                'subcategory': 'flood',
                'units': 'wetdry',
                'layer_type': 'vector',
                'data_type': 'polygon'
            }
            exposure_keywords = {
                'subcategory': 'structure',
                'units': 'building_type',
                'layer_type': 'vector',
                'data_type': 'polygon'
            }
            ifs =  if_manager.filter_by_keywords(hazard_keywords,
            exposure_keywords)

        :param hazard_keywords: The keywords of the hazard.
        :type hazard_keywords: dict

        :param exposure_keywords: The keywords of the exposure.
        :type exposure_keywords: dict
        """
        return self.registry.filter_by_keyword_string(hazard_keywords,
                                                      exposure_keywords)

    def filter_by_metadata(self, metadata_key, metadata_value):
        """Return IF classes given its metadata key and value.

        .. example::

            if_manager = ImpactFunctionManager()
            metadata_key = 'author'
            metadata_value = 'Akbar Gumbira'
            ifs =  if_manager.filter_by_metadata(metadata_key,
            metadata_value)

        :param metadata_key: The key of the metadata e.g 'id', 'name'
        :type metadata_key: str

        :param metadata_value: The value of the metadata, e.g for the key
            'id' the value is 'FloodNativePolygonExperimentalFunction'
        :type metadata_value: str, dict

        :return: Impact Function classes match the arguments
        :rtype: list
        """
        return self.registry.filter_by_metadata(metadata_key, metadata_value)

    @staticmethod
    def get_function_id(impact_function):
        """Get the ID of the impact function.

        :param impact_function: Class of an impact function
        :type impact_function: safe.impact_functions.base.ImpactFunction

        :returns: The ID of the impact function specified in its metadata.
        :rtype: str
        """
        return impact_function.metadata().as_dict().get('id', None)

    @staticmethod
    def get_function_title(impact_function):
        """Get title of the impact function.

        :param impact_function: Class of an impact function
        :type impact_function: safe.impact_functions.base.ImpactFunction

        :returns: The title of the impact function specified in its metadata.
        :rtype: str
        """
        return impact_function.metadata().as_dict().get('title', None)

    @staticmethod
    def get_function_name(impact_function):
        """Get the human readable name of the impact function.

        :param impact_function: Class of an impact function.
        :type impact_function: safe.impact_functions.base.ImpactFunction
        """
        return impact_function.metadata().as_dict().get('name', None)

    @staticmethod
    def get_function_type(impact_function):
        """Return the impact function type.

        :param impact_function: The impact function.
        :type impact_function: safe.impact_functions.base.ImpactFunction
        """
        return impact_function.function_type()

    def allowed_subcategories(self, category=None):
        """Determine allowed subcategories, optionally filtered by category.

        :param category: Optional category which will be used to subset the
            allowed subcategories. If omitted, all supported subcategories will
            be returned (for both hazard and exposure). Default is None.
        :type category: str

        :returns: A list of strings is returned.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            my_allowed_subcategories = impact_function.metadata()\
                .allowed_subcategories(category)
            result = add_to_list(result, my_allowed_subcategories)
        return result

    def allowed_data_types(self, subcategory):
        """Determine allowed data types for all impact functions.

        It uses subcategory as a filter.

        Passing a subcategory is required otherwise the context of the
        data_type(s) would be ambiguous (i.e. whether they can be used as
        exposure or hazards).

        :param subcategory: Required subcategory which will be used to subset
            the allowed data_types.
        :type subcategory: str

        :returns: A list of one or more strings is returned.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            my_allowed_data_types = impact_function.metadata() \
                .allowed_data_types(subcategory)
            result = add_to_list(result, my_allowed_data_types)
        return result

    def allowed_units(self, subcategory, data_type):
        """Determine allowed units from all impact functions.


        It uses subcategory and data_type as a filter.

        .. note:: One data_type could be  used by more than one subcategory,
            so we need to explicitly pass the subcategory to this function.

        :param subcategory: Required subcategory which will be used to subset
            the allowed data_types.
        :type subcategory: str

        :param data_type: Required data_type which will be used to subset the
            allowed units.
        :type data_type: str

        :returns: A list of one or more strings is returned.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            my_allowed_units = impact_function.metadata()\
                .allowed_units(subcategory, data_type)
            result = add_to_list(result, my_allowed_units)
        return result

    def units_for_layer(self, subcategory, layer_type, data_type):
        """Get the valid units for a layer.

        Example usage::

            foo  = units_for_layer('flood', 'vector', 'polygon')
            print foo

        Would output this::

            {'Wet/Dry': ['wet','dry']}

        While passing a raster layer::

            foo  = units_for_layer('flood', 'raster', None)
            print foo

        Might return this::

            {
                'metres': None,
                'feet': None,
                'wet/dry': ['wet', 'dry'],
            }

        In the returned dictionary the keys are unit types and
        the values are the categories (if any) applicable for that unit type.

        :param subcategory: The subcategory for this layer.
        :type subcategory: str

        :param layer_type: The type for this layer. Valid values would be,
            'raster' or 'vector'.
        :type layer_type: str

        :param data_type: The data_type for this layer. Valid possibilities
            would be 'numeric' (for raster), point, line, polygon
            (for vectors).
        :type data_type: str

        :returns: A dictionary as per the example above where each key
            represents a unit and each value that is not None represents a
            list of categories.
        :rtype: dict
        """
        result = []
        for impact_function in self.impact_functions:
            my_units = impact_function.metadata()\
                .units_for_layer(subcategory, layer_type, data_type)
            result = add_to_list(result, my_units)
        return result

    def categories_for_layer(self, layer_type, data_type):
        """Return a list of valid categories for a layer.

        This method is used to determine if a given layer can be used as a
        hazard, exposure or aggregation layer.

        Example usage::

            foo  = categories_for_layer('vector', 'polygon')
            print foo

        Would output this::

            ['hazard', 'exposure', 'aggregation']

        While passing a vector point layer::

            foo  = units_for_layer('vector', 'point')
            print foo

        Might return this::

            ['hazard', 'exposure']

        In the returned the values are categories (if any) applicable for that
        layer_type and data_type.

        :param layer_type: The type for this layer. Valid values would be,
            'raster' or 'vector'.
        :type layer_type: str

        :param data_type: The data_type for this layer. Valid possibilities
            would be 'numeric' (for raster), point, line, polygon
            (for vectors).
        :type data_type: str

        :returns: A list as per the example above where each value represents
            a valid category.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            categories = impact_function.metadata()\
                .categories_for_layer(layer_type, data_type)
            result = add_to_list(result, categories)
        categories_definitions = []
        for category in result:
            if category == 'hazard':
                categories_definitions.append(hazard_definition)
            elif category == 'exposure':
                categories_definitions.append(exposure_definition)
            else:
                raise Exception('Unsupported categories')
        return categories_definitions

    def subcategories_for_layer(self, category, layer_type, data_type):
        """Return a list of valid subcategories for a layer.

        This method is used to determine which subcategories a given layer
        can be for.

        Example usage::

            foo  = subcategories_for_layer('vector', 'polygon', 'exposure')
            print foo

        Would output this::

            ['flood', 'landuse']

        In the returned the values are categories (if any) applicable for that
        layer_type and data_type.

        :param layer_type: The type for this layer. Valid values would be,
            'raster' or 'vector'.
        :type layer_type: str

        :param data_type: The data_type for this layer. Valid possibilities
            would be 'numeric' (for raster), point, line, polygon
            (for vectors).
        :type data_type: str

        :param category: The category for this layer. Valid possibilities
            would be 'hazard', 'exposure' and 'aggregation'.
        :type category: str


        :returns: A list as per the example above where each value represents
            a valid subcategory.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            subcategories = impact_function.metadata()\
                .subcategories_for_layer(category, layer_type, data_type)
            result = add_to_list(result, subcategories)
        return result

    def get_available_hazards(self, impact_function=None, ascending=True):
        """Return a list of valid available hazards for an impact function.

        If impact_function is None, return all available hazards

        .. versionadded:: 2.2

        :param impact_function: Impact Function object.
        :type impact_function: FunctionProvider

        :param ascending: Sort ascending or not.
        :type ascending: bool

        :returns: A list of hazard full metadata.
        :rtype: list
        """

        hazards = []
        if impact_function is None:
            for impact_function in self.impact_functions:
                add_to_list(hazards, impact_function.metadata().get_hazards())

        else:
            # noinspection PyUnresolvedReferences
            hazards = impact_function.metadata().get_hazards()

        # make it sorted
        if ascending:
            hazards = sorted(hazards, key=lambda k: k['id'])

        return hazards

    def get_functions_for_hazard(self, hazard):
        """Return all function metadata that has hazard in their metadata.

        .. versionadded:: 2.2

        :param hazard: Dictionary that represent the hazard
        :type hazard: dict

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_hazard(hazard):
                impact_functions_metadata.append(
                    impact_function.metadata().as_dict())

        return impact_functions_metadata

    def get_functions_for_hazard_id(self, hazard_id):
        """Return all function metadata that has hazard_id in their metadata.

        .. versionadded:: 2.2

        :param hazard_id: String that represent the hazard id.
        :type hazard_id: str

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_hazard_id(hazard_id):
                impact_functions_metadata.append(
                    impact_function.metadata().as_dict())

        return impact_functions_metadata

    def get_available_exposures(self, impact_function=None, ascending=True):
        """Return a list of valid available exposures for an impact function.

        If impact_function is None, return all available exposures

        .. versionadded:: 2.2

        :param impact_function: Impact Function object.
        :type impact_function: FunctionProvider

        :param ascending: Sort ascending or not.
        :type ascending: bool

        :returns: A list of exposures full metadata.
        :rtype: list
        """

        exposures = []
        if impact_function is None:
            for impact_function in self.impact_functions:
                add_to_list(exposures,
                            impact_function.metadata().get_exposures())

        else:
            # noinspection PyUnresolvedReferences
            exposures = impact_function.metadata().get_exposures()

        # make it sorted
        if ascending:
            exposures = sorted(exposures, key=lambda k: k['id'])

        return exposures

    def get_functions_for_exposure(self, exposure):
        """Return all function metadata that has exposure in their metadata.

        .. versionadded:: 2.2

        :param exposure: Dictionary that represent the exposure
        :type exposure: dict

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_exposure(exposure):
                impact_functions_metadata.append(
                    impact_function.metadata().as_dict())

        return impact_functions_metadata

    def get_functions_for_exposure_id(self, exposure_id):
        """Return all function metadata that has exposure_id in their metadata.

        .. versionadded:: 2.2

        :param exposure_id: String that represent the exposure id.
        :type exposure_id: str

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_exposure_id(exposure_id):
                impact_functions_metadata.append(
                    impact_function.metadata().as_dict())

        return impact_functions_metadata

    def get_functions_for_constraint(self,
                                     hazard,
                                     exposure,
                                     hazard_constraint=None,
                                     exposure_constraint=None):
        """Get all impact functions that match the hazard n exposure metadata.

        :param hazard: The hazard metadata.
        :type hazard: dict

        :param exposure: The exposure metadata.
        :type exposure: dict

        :param hazard_constraint:
        :param exposure_constraint:
        :return:
        """
        result = []
        if_hazard = self.get_functions_for_hazard(hazard)
        if_exposure = self.get_functions_for_exposure(exposure)
        if_exposure_id = [function['id'] for function in if_exposure]

        for f in if_hazard:
            if f['id'] in if_exposure_id:
                if (not hazard_constraint or hazard_constraint
                        in f['categories']['hazard']['layer_constraints']):
                    if (not exposure_constraint or exposure_constraint in
                            f['categories']['exposure']['layer_constraints']):
                        result.append(f)

        return result
class ImpactFunctionManager(object):
    """Class for managing metadata for all impact function.

    .. versionadded:: 2.1
    """

    def __init__(self):
        """Constructor."""
        # Singleton Registry to track all the registered Impact Functions
        self.registry = Registry()

    @property
    def impact_functions(self):
        """Return all registered impact functions."""
        return self.registry.impact_functions

    def get_instance(self, class_name):
        """Return an instance of an impact function given its class name.

        .. example::

            if_manager = ImpactFunctionManager()
            if_class_name = 'FloodBuildingImpactFunction'
            if =  if_manager.get_instance(if_class_name)

        :param class_name: The name of IF class.
        :type class_name: str

        :return: Impact function instance that matches the argument.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        return self.registry.get_instance(class_name)

    def get_class(self, class_name):
        """Return the class of an impact function given its class name.

        .. example::

            if_manager = ImpactFunctionManager()
            if_class_name = 'FloodBuildingImpactFunction'
            if_class =  if_manager.get_class(if_class_name)

        :param class_name: the name of IF class
        :type class_name: str

        :return: impact function class that matches the argument.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        return self.registry.get_class(class_name)

    def get(self, impact_function_id):
        """Return an instance of an impact function given its ID.

        This is a preferred way to get an instance of IF. IF should have a
        unique human readable ID in their metadata.

        .. example::

            if_manager = ImpactFunctionManager()
            if_id = 'FloodBuildingImpactFunction'
            if =  if_manager.get(if_id)

        :param impact_function_id: The ID of impact function in the metadata.
        :type impact_function_id: str

        :return An Impact function instance that has matched id.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        impact_functions = self.registry.filter_by_metadata("id", impact_function_id)
        if len(impact_functions) == 0:
            raise Exception("Impact function with ID: %s not found" % impact_function_id)
        elif len(impact_functions) > 1:
            raise Exception("There are some Impact Functions that have the same ID: %s" % impact_function_id)
        return impact_functions[0].instance()

    def filter(self, hazard_metadata=None, exposure_metadata=None):
        """Get available impact functions from hazard and exposure metadata.

        Disabled impact function will not be loaded.

        .. example::

            if_manager = ImpactFunctionManager()
            hazard_metadata = {
                'subcategory': hazard_flood,
                'units': unit_wetdry,
                'layer_constraints': layer_vector_polygon
            }
            exposure_metadata = {
                'subcategory': exposure_structure,
                'units': unit_building_type_type,
                'layer_constraints': layer_vector_polygon
            }
            ifs =  if_manager.filter(hazard_metadata, exposure_metadata)

        :param hazard_metadata: The metadata of the hazard.
        :type hazard_metadata: dict

        :param exposure_metadata: The metadata of the exposure.
        :type exposure_metadata: dict
        """
        return self.registry.filter(hazard_metadata, exposure_metadata)

    def filter_by_keywords(self, hazard_keywords=None, exposure_keywords=None):
        """Get available impact functions from hazard and exposure keywords.

        Disabled impact function will not be loaded.

        .. example::

            if_manager = ImpactFunctionManager()
            hazard_keywords = {
                'subcategory': 'flood',
                'units': 'wetdry',
                'layer_type': 'vector',
                'data_type': 'polygon'
            }
            exposure_keywords = {
                'subcategory': 'structure',
                'units': 'building_type',
                'layer_type': 'vector',
                'data_type': 'polygon'
            }
            ifs =  if_manager.filter_by_keywords(hazard_keywords,
            exposure_keywords)

        :param hazard_keywords: The keywords of the hazard.
        :type hazard_keywords: dict

        :param exposure_keywords: The keywords of the exposure.
        :type exposure_keywords: dict
        """
        return self.registry.filter_by_keyword_string(hazard_keywords, exposure_keywords)

    def filter_by_metadata(self, metadata_key, metadata_value):
        """Return IF classes given its metadata key and value.

        .. example::

            if_manager = ImpactFunctionManager()
            metadata_key = 'author'
            metadata_value = 'Akbar Gumbira'
            ifs =  if_manager.filter_by_metadata(metadata_key,
            metadata_value)

        :param metadata_key: The key of the metadata e.g 'id', 'name'
        :type metadata_key: str

        :param metadata_value: The value of the metadata, e.g for the key
            'id' the value is 'FloodNativePolygonExperimentalFunction'
        :type metadata_value: str, dict

        :return: Impact Function classes match the arguments
        :rtype: list
        """
        return self.registry.filter_by_metadata(metadata_key, metadata_value)

    @staticmethod
    def get_function_id(impact_function):
        """Get the ID of the impact function.

        :param impact_function: Class of an impact function
        :type impact_function: safe.impact_functions.base.ImpactFunction

        :returns: The ID of the impact function specified in its metadata.
        :rtype: str
        """
        return impact_function.metadata().as_dict().get("id", None)

    @staticmethod
    def get_function_title(impact_function):
        """Get title of the impact function.

        :param impact_function: Class of an impact function
        :type impact_function: safe.impact_functions.base.ImpactFunction

        :returns: The title of the impact function specified in its metadata.
        :rtype: str
        """
        return impact_function.metadata().as_dict().get("title", None)

    @staticmethod
    def get_function_name(impact_function):
        """Get the human readable name of the impact function.

        :param impact_function: Class of an impact function.
        :type impact_function: safe.impact_functions.base.ImpactFunction
        """
        return impact_function.metadata().as_dict().get("name", None)

    @staticmethod
    def get_function_type(impact_function):
        """Return the impact function type.

        :param impact_function: The impact function.
        :type impact_function: safe.impact_functions.base.ImpactFunction
        """
        return impact_function.function_type()

    def allowed_subcategories(self, category=None):
        """Determine allowed subcategories, optionally filtered by category.

        :param category: Optional category which will be used to subset the
            allowed subcategories. If omitted, all supported subcategories will
            be returned (for both hazard and exposure). Default is None.
        :type category: str

        :returns: A list of strings is returned.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            my_allowed_subcategories = impact_function.metadata().allowed_subcategories(category)
            result = add_to_list(result, my_allowed_subcategories)
        return result

    def allowed_data_types(self, subcategory):
        """Determine allowed data types for all impact functions.

        It uses subcategory as a filter.

        Passing a subcategory is required otherwise the context of the
        data_type(s) would be ambiguous (i.e. whether they can be used as
        exposure or hazards).

        :param subcategory: Required subcategory which will be used to subset
            the allowed data_types.
        :type subcategory: str

        :returns: A list of one or more strings is returned.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            my_allowed_data_types = impact_function.metadata().allowed_data_types(subcategory)
            result = add_to_list(result, my_allowed_data_types)
        return result

    def allowed_units(self, subcategory, data_type):
        """Determine allowed units from all impact functions.


        It uses subcategory and data_type as a filter.

        .. note:: One data_type could be  used by more than one subcategory,
            so we need to explicitly pass the subcategory to this function.

        :param subcategory: Required subcategory which will be used to subset
            the allowed data_types.
        :type subcategory: str

        :param data_type: Required data_type which will be used to subset the
            allowed units.
        :type data_type: str

        :returns: A list of one or more strings is returned.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            my_allowed_units = impact_function.metadata().allowed_units(subcategory, data_type)
            result = add_to_list(result, my_allowed_units)
        return result

    def units_for_layer(self, subcategory, layer_type, data_type):
        """Get the valid units for a layer.

        Example usage::

            foo  = units_for_layer('flood', 'vector', 'polygon')
            print foo

        Would output this::

            {'Wet/Dry': ['wet','dry']}

        While passing a raster layer::

            foo  = units_for_layer('flood', 'raster', None)
            print foo

        Might return this::

            {
                'metres': None,
                'feet': None,
                'wet/dry': ['wet', 'dry'],
            }

        In the returned dictionary the keys are unit types and
        the values are the categories (if any) applicable for that unit type.

        :param subcategory: The subcategory for this layer.
        :type subcategory: str

        :param layer_type: The type for this layer. Valid values would be,
            'raster' or 'vector'.
        :type layer_type: str

        :param data_type: The data_type for this layer. Valid possibilities
            would be 'numeric' (for raster), point, line, polygon
            (for vectors).
        :type data_type: str

        :returns: A dictionary as per the example above where each key
            represents a unit and each value that is not None represents a
            list of categories.
        :rtype: dict
        """
        result = []
        for impact_function in self.impact_functions:
            my_units = impact_function.metadata().units_for_layer(subcategory, layer_type, data_type)
            result = add_to_list(result, my_units)
        return result

    def categories_for_layer(self, layer_type, data_type):
        """Return a list of valid categories for a layer.

        This method is used to determine if a given layer can be used as a
        hazard, exposure or aggregation layer.

        Example usage::

            foo  = categories_for_layer('vector', 'polygon')
            print foo

        Would output this::

            ['hazard', 'exposure', 'aggregation']

        While passing a vector point layer::

            foo  = units_for_layer('vector', 'point')
            print foo

        Might return this::

            ['hazard', 'exposure']

        In the returned the values are categories (if any) applicable for that
        layer_type and data_type.

        :param layer_type: The type for this layer. Valid values would be,
            'raster' or 'vector'.
        :type layer_type: str

        :param data_type: The data_type for this layer. Valid possibilities
            would be 'numeric' (for raster), point, line, polygon
            (for vectors).
        :type data_type: str

        :returns: A list as per the example above where each value represents
            a valid category.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            categories = impact_function.metadata().categories_for_layer(layer_type, data_type)
            result = add_to_list(result, categories)
        categories_definitions = []
        for category in result:
            if category == "hazard":
                categories_definitions.append(hazard_definition)
            elif category == "exposure":
                categories_definitions.append(exposure_definition)
            else:
                raise Exception("Unsupported categories")
        return categories_definitions

    def subcategories_for_layer(self, category, layer_type, data_type):
        """Return a list of valid subcategories for a layer.

        This method is used to determine which subcategories a given layer
        can be for.

        Example usage::

            foo  = subcategories_for_layer('vector', 'polygon', 'exposure')
            print foo

        Would output this::

            ['flood', 'landuse']

        In the returned the values are categories (if any) applicable for that
        layer_type and data_type.

        :param layer_type: The type for this layer. Valid values would be,
            'raster' or 'vector'.
        :type layer_type: str

        :param data_type: The data_type for this layer. Valid possibilities
            would be 'numeric' (for raster), point, line, polygon
            (for vectors).
        :type data_type: str

        :param category: The category for this layer. Valid possibilities
            would be 'hazard', 'exposure' and 'aggregation'.
        :type category: str


        :returns: A list as per the example above where each value represents
            a valid subcategory.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            subcategories = impact_function.metadata().subcategories_for_layer(category, layer_type, data_type)
            result = add_to_list(result, subcategories)
        return result

    def get_available_hazards(self, impact_function=None, ascending=True):
        """Return a list of valid available hazards for an impact function.

        If impact_function is None, return all available hazards

        .. versionadded:: 2.2

        :param impact_function: Impact Function object.
        :type impact_function: FunctionProvider

        :param ascending: Sort ascending or not.
        :type ascending: bool

        :returns: A list of hazard full metadata.
        :rtype: list
        """

        hazards = []
        if impact_function is None:
            for impact_function in self.impact_functions:
                add_to_list(hazards, impact_function.metadata().get_hazards())

        else:
            # noinspection PyUnresolvedReferences
            hazards = impact_function.metadata().get_hazards()

        # make it sorted
        if ascending:
            hazards = sorted(hazards, key=lambda k: k["id"])

        return hazards

    def get_functions_for_hazard(self, hazard):
        """Return all function metadata that has hazard in their metadata.

        .. versionadded:: 2.2

        :param hazard: Dictionary that represent the hazard
        :type hazard: dict

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_hazard(hazard):
                impact_functions_metadata.append(impact_function.metadata().as_dict())

        return impact_functions_metadata

    def get_functions_for_hazard_id(self, hazard_id):
        """Return all function metadata that has hazard_id in their metadata.

        .. versionadded:: 2.2

        :param hazard_id: String that represent the hazard id.
        :type hazard_id: str

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_hazard_id(hazard_id):
                impact_functions_metadata.append(impact_function.metadata().as_dict())

        return impact_functions_metadata

    def get_available_exposures(self, impact_function=None, ascending=True):
        """Return a list of valid available exposures for an impact function.

        If impact_function is None, return all available exposures

        .. versionadded:: 2.2

        :param impact_function: Impact Function object.
        :type impact_function: FunctionProvider

        :param ascending: Sort ascending or not.
        :type ascending: bool

        :returns: A list of exposures full metadata.
        :rtype: list
        """

        exposures = []
        if impact_function is None:
            for impact_function in self.impact_functions:
                add_to_list(exposures, impact_function.metadata().get_exposures())

        else:
            # noinspection PyUnresolvedReferences
            exposures = impact_function.metadata().get_exposures()

        # make it sorted
        if ascending:
            exposures = sorted(exposures, key=lambda k: k["id"])

        return exposures

    def get_functions_for_exposure(self, exposure):
        """Return all function metadata that has exposure in their metadata.

        .. versionadded:: 2.2

        :param exposure: Dictionary that represent the exposure
        :type exposure: dict

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_exposure(exposure):
                impact_functions_metadata.append(impact_function.metadata().as_dict())

        return impact_functions_metadata

    def get_functions_for_exposure_id(self, exposure_id):
        """Return all function metadata that has exposure_id in their metadata.

        .. versionadded:: 2.2

        :param exposure_id: String that represent the exposure id.
        :type exposure_id: str

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_exposure_id(exposure_id):
                impact_functions_metadata.append(impact_function.metadata().as_dict())

        return impact_functions_metadata

    def get_functions_for_constraint(self, hazard, exposure, hazard_constraint=None, exposure_constraint=None):
        """Get all impact functions that match the hazard n exposure metadata.

        :param hazard: The hazard metadata.
        :type hazard: dict

        :param exposure: The exposure metadata.
        :type exposure: dict

        :param hazard_constraint:
        :param exposure_constraint:
        :return:
        """
        result = []
        if_hazard = self.get_functions_for_hazard(hazard)
        if_exposure = self.get_functions_for_exposure(exposure)
        if_exposure_id = [function["id"] for function in if_exposure]

        for f in if_hazard:
            if f["id"] in if_exposure_id:
                if not hazard_constraint or hazard_constraint in f["categories"]["hazard"]["layer_constraints"]:
                    if (
                        not exposure_constraint
                        or exposure_constraint in f["categories"]["exposure"]["layer_constraints"]
                    ):
                        result.append(f)

        return result
示例#28
0
class RasterReclassifyDialog(QDialog, FORM_CLASS):

    def __init__(self, parent=None, iface=None):
        """Constructor for Raster Reclassification to Vector Polygon.

        .. versionadded: 3.4

        :param parent: Optional widget to use as parent
        :type parent: QWidget

        :param iface: An instance of QGisInterface
        :type iface: QGisInterface
        """
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setupUi(self)

        self.setWindowTitle(self.tr('Raster Reclassification'))

        self.iface = iface

        self.if_registry = Registry()
        self.keyword_io = KeywordIO()

        # populate raster input
        self.cbo_raster_input.clear()
        registry = QgsMapLayerRegistry.instance()
        # MapLayers returns a QMap<QString id, QgsMapLayer layer>
        layers = registry.mapLayers().values()
        for layer in layers:
            try:
                name = layer.name()
                source = layer.id()
                layer_purpose = self.keyword_io.read_keywords(
                    layer, 'layer_purpose')
                if (isinstance(layer, QgsRasterLayer) and
                            layer_purpose == 'hazard'):
                    add_ordered_combo_item(
                        self.cbo_raster_input, self.tr(name), source)

            except Exception as e:
                raise e

        # self.input_list_parameter = InputListParameter()
        # self.input_list_parameter.name = 'Thresholds'
        # self.input_list_parameter.description = (
        #     'List of thresholds of values used in reclassification.')
        # self.input_list_parameter.help_text = 'list of thresholds used'
        # self.input_list_parameter.maximum_item_count = 100
        # self.input_list_parameter.minimum_item_count = 1
        # self.input_list_parameter.element_type = float
        # self.input_list_parameter.value = [0.0, 1.0]
        # self.input_list_parameter.ordering = \
        #     InputListParameter.AscendingOrder
        # self.thresholds_widget = InputListParameterWidget(
        #     self.input_list_parameter)

        # self.threshold_editor.layout().addWidget(self.thresholds_widget)

        # Set up context help
        self.help_button = self.button_box.button(QtGui.QDialogButtonBox.Help)
        self.ok_button = self.button_box.button(QtGui.QDialogButtonBox.Ok)
        # self.cancel_button = self.button_box.button(
        #     QtGui.QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        # Allow toggling the help button
        self.help_button.setCheckable(True)
        self.help_button.toggled.connect(self.help_toggled)
        self.main_stacked_widget.setCurrentIndex(1)
        # adapt layer changed
        self.cbo_raster_input.currentIndexChanged.connect(self.raster_changed)
        self.raster_changed(self.cbo_raster_input.currentIndex())

    # noinspection PyPep8Naming
    @pyqtSlot(int)
    def raster_changed(self, index):
        """Executed when raster is changed

        :param index: index of the selected raster
        :return:
        """
        registry = QgsMapLayerRegistry.instance()
        layer_id = self.cbo_raster_input.itemData(
            index, QtCore.Qt.UserRole)
        layer = registry.mapLayer(layer_id)
        layer_purpose = self.keyword_io.read_keywords(layer, 'layer_purpose')
        if layer_purpose == 'hazard':
            impact_function = self.if_registry.filter_by_hazard(
                self.if_registry.impact_functions,
                self.keyword_io.read_keywords(layer)
            )
        elif layer_purpose == 'exposure':
            impact_function = self.if_registry.filter_by_exposure(
                self.if_registry.impact_functions,
                self.keyword_io.read_keywords(layer)
            )
        else:
            impact_function = []

        if impact_function:
            parameters_dict = impact_function[0].parameters
            threshold_list = []
            for param_key, param_value in parameters_dict.iteritems():
                if 'threshold' in param_key:
                    threshold_list.append(param_value)

            if threshold_list:
                param_container = ParameterContainer(threshold_list)
                param_container.setup_ui(must_scroll=False)

                self.threshold_editor.layout().addWidget(param_container)
            else:
                empty_threshold_label = QLabel(
                    self.tr('No threshold configuration available '
                            'for this layer'))
                self.threshold_editor.layout().addWidget(
                    empty_threshold_label)

    @pyqtSlot()
    @pyqtSignature('bool')  # prevents actions being handled twice
    def help_toggled(self, flag):
        """Show or hide the help tab in the stacked widget.

        .. versionadded: 3.4

        :param flag: Flag indicating whether help should be shown or hidden.
        :type flag: bool
        """
        if flag:
            self.help_button.setText(self.tr('Hide Help'))
            self.show_help()
        else:
            self.help_button.setText(self.tr('Show Help'))
            self.hide_help()

    def hide_help(self):
        """Hide the usage info from the user.

        .. versionadded:: 3.4
        """
        self.main_stacked_widget.setCurrentIndex(1)

    def show_help(self):
        """Show usage info to the user.

        .. versionadded: 3.4
        """
        # Read the header and footer html snippets
        self.main_stacked_widget.setCurrentIndex(0)
        header = html_header()
        footer = html_footer()

        string = header

        message = raster_reclassify_help()
        string += message.to_html()
        string += footer

        self.help_web_view.setHtml(string)

    def validate(self):
        if self.cbo_raster_input.currentIndex() < 0:
            self.ok_button.setEnabled(False)
        else:
            self.ok_button.setEnabled(True)

    def accept(self):
        """Do raster reclassification and display it in QGIS

        .. versionadded: 3.4

        :return:
        """
        registry = QgsMapLayerRegistry.instance()
        try:
            index = self.cbo_raster_input.currentIndex()
            layer_id = self.cbo_raster_input.itemData(
                index, QtCore.Qt.UserRole)
            layer = registry.mapLayer(layer_id)
            class_attribute = 'class'
            # extract thresholds
            thresholds_list = self.thresholds_widget.get_parameter().value
            thresholds_list.append(None)
            ranges = ranges_according_thresholds_list(thresholds_list)

            path = reclassify_polygonize(
                layer.source(), ranges, name_field=class_attribute)

            # load layer to QGIS
            title = self.tr('%s classified') % self.tr(layer.name())
            layer = QgsVectorLayer(path, title, 'ogr')
            registry.addMapLayer(layer)
        except Exception as e:
            LOGGER.exception(e)

        QtGui.qApp.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
        self.disable_busy_cursor()
        self.done(QDialog.Accepted)

    @staticmethod
    def disable_busy_cursor():
        """Disable the hourglass cursor.

        TODO: this is duplicated from dock.py
        """
        while QtGui.qApp.overrideCursor() is not None and \
                        QtGui.qApp.overrideCursor().shape() == \
                        QtCore.Qt.WaitCursor:
            QtGui.qApp.restoreOverrideCursor()

    def reject(self):
        """Redefinition of the reject() method.

        It will call the super method.
        """
        # add our own logic here...

        super(RasterReclassifyDialog, self).reject()
示例#29
0
 def test_list(self):
     """TestRegistry: Test list all register IFs."""
     registry = Registry()
     impact_functions = registry.list()
     self.assertItemsEqual(EXPECTED_IF, impact_functions)
示例#30
0
    def __init__(self, parent=None, iface=None):
        """Constructor for Raster Reclassification to Vector Polygon.

        .. versionadded: 3.4

        :param parent: Optional widget to use as parent
        :type parent: QWidget

        :param iface: An instance of QGisInterface
        :type iface: QGisInterface
        """
        QDialog.__init__(self, parent)
        self.parent = parent
        self.setupUi(self)

        self.setWindowTitle(self.tr('Raster Reclassification'))

        self.iface = iface

        self.if_registry = Registry()
        self.keyword_io = KeywordIO()

        # populate raster input
        self.cbo_raster_input.clear()
        registry = QgsMapLayerRegistry.instance()
        # MapLayers returns a QMap<QString id, QgsMapLayer layer>
        layers = registry.mapLayers().values()
        for layer in layers:
            try:
                name = layer.name()
                source = layer.id()
                layer_purpose = self.keyword_io.read_keywords(
                    layer, 'layer_purpose')
                if (isinstance(layer, QgsRasterLayer) and
                            layer_purpose == 'hazard'):
                    add_ordered_combo_item(
                        self.cbo_raster_input, self.tr(name), source)

            except Exception as e:
                raise e

        # self.input_list_parameter = InputListParameter()
        # self.input_list_parameter.name = 'Thresholds'
        # self.input_list_parameter.description = (
        #     'List of thresholds of values used in reclassification.')
        # self.input_list_parameter.help_text = 'list of thresholds used'
        # self.input_list_parameter.maximum_item_count = 100
        # self.input_list_parameter.minimum_item_count = 1
        # self.input_list_parameter.element_type = float
        # self.input_list_parameter.value = [0.0, 1.0]
        # self.input_list_parameter.ordering = \
        #     InputListParameter.AscendingOrder
        # self.thresholds_widget = InputListParameterWidget(
        #     self.input_list_parameter)

        # self.threshold_editor.layout().addWidget(self.thresholds_widget)

        # Set up context help
        self.help_button = self.button_box.button(QtGui.QDialogButtonBox.Help)
        self.ok_button = self.button_box.button(QtGui.QDialogButtonBox.Ok)
        # self.cancel_button = self.button_box.button(
        #     QtGui.QDialogButtonBox.Cancel)
        self.button_box.accepted.connect(self.accept)
        self.button_box.rejected.connect(self.reject)
        # Allow toggling the help button
        self.help_button.setCheckable(True)
        self.help_button.toggled.connect(self.help_toggled)
        self.main_stacked_widget.setCurrentIndex(1)
        # adapt layer changed
        self.cbo_raster_input.currentIndexChanged.connect(self.raster_changed)
        self.raster_changed(self.cbo_raster_input.currentIndex())
示例#31
0
 def test_list(self):
     """TestRegistry: Test list all register IFs."""
     registry = Registry()
     impact_functions = registry.list()
     self.assertItemsEqual(EXPECTED_IF, impact_functions)
class ImpactFunctionManager(object):
    """Class for managing metadata for all impact function.

    .. versionadded:: 2.1
    """

    def __init__(self):
        """Constructor."""
        # Singleton Registry to track all the registered Impact Functions
        self.registry = Registry()

    @property
    def impact_functions(self):
        """Return all registered impact functions."""
        return self.registry.impact_functions

    def get_instance(self, class_name):
        """Return an instance of an impact function given its class name.

        .. example::

            if_manager = ImpactFunctionManager()
            if_class_name = 'FloodBuildingImpactFunction'
            if =  if_manager.get_instance(if_class_name)

        :param class_name: The name of IF class.
        :type class_name: str

        :return: Impact function instance that matches the argument.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        return self.registry.get_instance(class_name)

    def get_class(self, class_name):
        """Return the class of an impact function given its class name.

        .. example::

            if_manager = ImpactFunctionManager()
            if_class_name = 'FloodBuildingImpactFunction'
            if_class =  if_manager.get_class(if_class_name)

        :param class_name: the name of IF class
        :type class_name: str

        :return: impact function class that matches the argument.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        return self.registry.get_class(class_name)

    def get(self, impact_function_id):
        """Return an instance of an impact function given its ID.

        This is a preferred way to get an instance of IF. IF should have a
        unique human readable ID in their metadata.

        .. example::

            if_manager = ImpactFunctionManager()
            if_id = 'FloodBuildingImpactFunction'
            if =  if_manager.get(if_id)

        :param impact_function_id: The ID of impact function in the metadata.
        :type impact_function_id: str

        :return An Impact function instance that has matched id.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        impact_functions = self.registry.filter_by_metadata(
            'id', impact_function_id)
        if len(impact_functions) == 0:
            raise Exception(
                'Impact function with ID: %s not found' % impact_function_id)
        elif len(impact_functions) > 1:
            raise Exception(
                'There are some Impact Functions that have the same ID: %s' %
                impact_function_id)
        return impact_functions[0].instance()

    def filter(self, hazard_metadata=None, exposure_metadata=None):
        """Get available impact functions from hazard and exposure metadata.

        Disabled impact function will not be loaded.

        .. example::

            if_manager = ImpactFunctionManager()
            hazard_metadata = {
                'subcategory': hazard_flood,
                'units': unit_wetdry,
                'layer_constraints': layer_vector_polygon
            }
            exposure_metadata = {
                'subcategory': exposure_structure,
                'units': unit_building_type_type,
                'layer_constraints': layer_vector_polygon
            }
            ifs =  if_manager.filter(hazard_metadata, exposure_metadata)

        :param hazard_metadata: The metadata of the hazard.
        :type hazard_metadata: dict

        :param exposure_metadata: The metadata of the exposure.
        :type exposure_metadata: dict
        """
        return self.registry.filter(hazard_metadata, exposure_metadata)

    def filter_by_keywords(
            self, hazard_keywords=None, exposure_keywords=None):
        """Get available impact functions from hazard and exposure keywords.

        Disabled impact function will not be loaded.

        .. example::

            if_manager = ImpactFunctionManager()
            hazard_keywords = {
                'subcategory': 'flood',
                'units': 'wetdry',
                'layer_type': 'vector',
                'data_type': 'polygon'
            }
            exposure_keywords = {
                'subcategory': 'structure',
                'units': 'building_type',
                'layer_type': 'vector',
                'data_type': 'polygon'
            }
            ifs =  if_manager.filter_by_keywords(hazard_keywords,
            exposure_keywords)

        :param hazard_keywords: The keywords of the hazard.
        :type hazard_keywords: dict

        :param exposure_keywords: The keywords of the exposure.
        :type exposure_keywords: dict
        """
        return self.registry.filter_by_keyword_string(
            hazard_keywords, exposure_keywords)

    def filter_by_metadata(self, metadata_key, metadata_value):
        """Return IF classes given its metadata key and value.

        .. example::

            if_manager = ImpactFunctionManager()
            metadata_key = 'author'
            metadata_value = 'Akbar Gumbira'
            ifs =  if_manager.filter_by_metadata(metadata_key,
            metadata_value)

        :param metadata_key: The key of the metadata e.g 'id', 'name'
        :type metadata_key: str

        :param metadata_value: The value of the metadata, e.g for the key
            'id' the value is 'FloodNativePolygonExperimentalFunction'
        :type metadata_value: str, dict

        :return: Impact Function classes match the arguments
        :rtype: list
        """
        return self.registry.filter_by_metadata(metadata_key, metadata_value)

    @staticmethod
    def get_function_id(impact_function):
        """Get the ID of the impact function.

        :param impact_function: Class of an impact function
        :type impact_function: safe.impact_functions.base.ImpactFunction

        :returns: The ID of the impact function specified in its metadata.
        :rtype: str
        """
        return impact_function.metadata().as_dict().get('id', None)

    @staticmethod
    def get_function_title(impact_function):
        """Get title of the impact function.

        :param impact_function: Class of an impact function
        :type impact_function: safe.impact_functions.base.ImpactFunction

        :returns: The title of the impact function specified in its metadata.
        :rtype: str
        """
        return impact_function.metadata().as_dict().get('title', None)

    @staticmethod
    def get_function_name(impact_function):
        """Get the human readable name of the impact function.

        :param impact_function: Class of an impact function.
        :type impact_function: safe.impact_functions.base.ImpactFunction
        """
        return impact_function.metadata().as_dict().get('name', None)

    @staticmethod
    def get_function_type(impact_function):
        """Return the impact function type.

        :param impact_function: The impact function.
        :type impact_function: safe.impact_functions.base.ImpactFunction
        """
        return impact_function.function_type()

    def get_functions_for_hazard(self, hazard):
        """Return all function metadata that has hazard in their metadata.

        .. versionadded:: 2.2

        :param hazard: Dictionary that represent the hazard
        :type hazard: dict

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_hazard(hazard):
                impact_functions_metadata.append(
                    impact_function.metadata().as_dict())

        return impact_functions_metadata

    def purposes_for_layer(self, layer_geometry_key):
        """Get purposes of a layer geometry id.

        :param layer_geometry_key: The geometry id
        :type layer_geometry_key: str

        """
        layer_purposes = []
        for impact_function in self.impact_functions:
            if_layer_purposes = impact_function.metadata().purposes_for_layer(
                layer_geometry_key)
            if if_layer_purposes:
                add_to_list(layer_purposes, if_layer_purposes)

        return layer_purposes

    def hazard_categories_for_layer(self, layer_geometry_key, hazard_key=None):
        """Get hazard categories form layer_geometry_key

        :param layer_geometry_key: The geometry id
        :type layer_geometry_key: str

        :param hazard_key: The hazard key
        :type hazard_key: str

        :returns: List of hazard_categories
        :rtype: list
        """
        hazard_categories = []
        for impact_function in self.impact_functions:
            if_hazard_categories = impact_function.metadata()\
                .hazard_categories_for_layer(layer_geometry_key, hazard_key)
            if if_hazard_categories:
                add_to_list(hazard_categories, if_hazard_categories)

        return hazard_categories

    def hazards_for_layer(self, layer_geometry_key, hazard_category_key=None):
        """Get hazard categories form layer_geometry_key

        :param layer_geometry_key: The geometry id
        :type layer_geometry_key: str

        :param hazard_category_key: The hazard category
        :type hazard_category_key: str

        :returns: List of hazard
        :rtype: list
        """
        hazards = []
        for impact_function in self.impact_functions:
            if_hazards = impact_function.metadata().hazards_for_layer(
                layer_geometry_key, hazard_category_key)
            if if_hazards:
                add_to_list(hazards, if_hazards)

        return hazards

    def exposures_for_layer(self, layer_geometry_key):
        """Get hazard categories form layer_geometry_key

        :param layer_geometry_key: The geometry id
        :type layer_geometry_key: str

        :returns: List of hazard
        :rtype: list
        """
        exposures = []
        for impact_function in self.impact_functions:
            if_exposures = impact_function.metadata().exposures_for_layer(
                layer_geometry_key)
            if if_exposures:
                add_to_list(exposures, if_exposures)

        return exposures

    def exposure_units_for_layer(
            self, exposure_key, layer_geometry_key, layer_mode_key):
        """Get hazard categories form layer_geometry_key

        :param exposure_key: The exposure key
        :type exposure_key: str

        :param layer_geometry_key: The geometry key
        :type layer_geometry_key: str

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :returns: List of exposure unit
        :rtype: list
        """
        exposure_units = []
        for impact_function in self.impact_functions:
            if_exposure_units = impact_function.metadata().\
                exposure_units_for_layer(
                    exposure_key, layer_geometry_key, layer_mode_key)
            if if_exposure_units:
                add_to_list(exposure_units, if_exposure_units)

        return exposure_units

    def continuous_hazards_units_for_layer(
            self, hazard_key, layer_geometry_key, layer_mode_key,
            hazard_category_key):
        """Get continuous hazard units.
        :param hazard_key: The hazard key
        :type hazard_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of continuous hazard unit
        :rtype: list
        """
        continuous_hazards_units = []
        for impact_function in self.impact_functions:
            if_continuous_hazard_units = impact_function.metadata().\
                continuous_hazards_units_for_layer(
                    hazard_key, layer_geometry_key, layer_mode_key,
                    hazard_category_key)
            if if_continuous_hazard_units:
                add_to_list(
                    continuous_hazards_units, if_continuous_hazard_units)

        return continuous_hazards_units

    def vector_hazards_classifications_for_layer(
            self, hazard_key, layer_geometry_key, layer_mode_key,
            hazard_category_key):
        """Get continuous hazard units.
        :param hazard_key: The hazard key
        :type hazard_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of vector_hazards_classifications
        :rtype: list
        """
        vector_hazards_classifications = []
        for impact_function in self.impact_functions:
            if_vector_hazards_classifications = impact_function.metadata().\
                vector_hazards_classifications_for_layer(
                    hazard_key, layer_geometry_key, layer_mode_key,
                    hazard_category_key)
            if if_vector_hazards_classifications:
                add_to_list(
                    vector_hazards_classifications,
                    if_vector_hazards_classifications)

        return vector_hazards_classifications

    def raster_hazards_classifications_for_layer(
            self, hazard_key, layer_geometry_key, layer_mode_key,
            hazard_category_key):
        """Get continuous hazard units.
        :param hazard_key: The hazard key
        :type hazard_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of raster_hazards_classifications
        :rtype: list
        """
        raster_hazards_classifications = []
        for impact_function in self.impact_functions:
            if_vector_hazards_classifications = impact_function.metadata().\
                raster_hazards_classifications_for_layer(
                    hazard_key, layer_geometry_key, layer_mode_key,
                    hazard_category_key)
            if if_vector_hazards_classifications:
                add_to_list(
                    raster_hazards_classifications,
                    if_vector_hazards_classifications)

        return raster_hazards_classifications

    def available_hazards(self, hazard_category_key, ascending=True):
        """available_hazards from hazard_category_key

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :param ascending: Sort ascending or not.
        :type ascending: bool

        :returns: List of available hazards
        :rtype: list
        """

        hazards = []
        for impact_function in self.impact_functions:
            if_hazards = impact_function.metadata(). \
                available_hazards(hazard_category_key)
            if if_hazards:
                add_to_list(hazards, if_hazards)

        # make it sorted
        if ascending and hazards:
            hazards = sorted(hazards, key=lambda k: k['key'])

        return hazards

    def available_exposures(self, ascending=True):
        """Return a list of valid available exposures

        :param ascending: Sort ascending or not.
        :type ascending: bool

        :returns: A list of exposures full metadata.
        :rtype: list
        """

        exposures = []
        for impact_function in self.impact_functions:
            if_exposures = impact_function.metadata().available_exposures()
            if if_exposures:
                add_to_list(exposures, if_exposures)

        # make it sorted
        if ascending and exposures:
            exposures = sorted(exposures, key=lambda k: k['key'])

        return exposures

    def functions_for_constraint(
            self, hazard_key, exposure_key, hazard_geometry_key=None,
            exposure_geometry_key=None, hazard_mode_key=None,
            exposure_mode_key=None):
        """Obtain all functions that match with the constraints

        :param hazard_key: The hazard key
        :type hazard_key: str

        :param exposure_key: the exposure key
        :type exposure_key: str

        :param hazard_geometry_key: The hazard geometry key
        :type hazard_geometry_key: str

        :param exposure_geometry_key: The exposure geometry key
        :type exposure_geometry_key: str

        :param hazard_mode_key: The hazard mode key
        :type hazard_mode_key: str

        :param exposure_mode_key: The exposure mode key
        :type exposure_mode_key: str

        :returns: List of matched Impact Function
        :rtype: list
        """
        impact_functions = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().is_function_for_constraint(
                    hazard_key, exposure_key, hazard_geometry_key,
                    exposure_geometry_key, hazard_mode_key, exposure_mode_key):
                impact_functions.append(impact_function.metadata().as_dict())

        return impact_functions

    def available_hazard_constraints(
            self, hazard_key, hazard_category_key):
        """Get hazard constraints for hazard_key and hazard_category_key

        :param hazard_key: The hazard key
        :type hazard_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of tuple of layer_mode and layer_geometry
        :rtype: list
        """
        hazard_constraints = []
        for impact_function in self.impact_functions:
            if_hazard_constraints = impact_function.metadata().\
                available_hazard_constraints(
                    hazard_key, hazard_category_key)
            if if_hazard_constraints:
                add_to_list(hazard_constraints, if_hazard_constraints)

        return hazard_constraints

    def available_exposure_constraints(self, exposure_key):
        """Get exposure constraints for exposure_key.

        :param exposure_key: The exposure key
        :type exposure_key: str

        :returns: List of tuple of layer_mode and layer_geometry
        :rtype: list
        """
        exposure_constraints = []
        for impact_function in self.impact_functions:
            if_exposure_constraints = impact_function.metadata(). \
                available_exposure_constraints(exposure_key)
            if if_exposure_constraints:
                add_to_list(exposure_constraints, if_exposure_constraints)

        return exposure_constraints

    def available_hazard_layer_modes(
            self, hazard_key, hazard_geometry_key, hazard_category_key):
        """Return all available layer_mode.

        :param hazard_key: The hazard key
        :type hazard_key: str

        :param hazard_geometry_key: The hazard geometry key
        :type hazard_geometry_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of layer_mode
        :rtype: list
        """
        layer_modes = []
        for impact_function in self.impact_functions:
            if_hazard_layer_mode = impact_function.metadata().\
                available_hazard_layer_mode(
                    hazard_key, hazard_geometry_key, hazard_category_key)
            if if_hazard_layer_mode:
                add_to_list(layer_modes, if_hazard_layer_mode)

        return layer_modes

    def available_exposure_layer_modes(
            self, exposure_key, exposure_geometry_key):
        """Get exposure layer mode for exposure_key.

        :param exposure_key: The exposure key
        :type exposure_key: str

        :param exposure_geometry_key: The exposure geometry key
        :type exposure_geometry_key: str

        :returns: List of layer_mode
        :rtype: list
        """
        layer_modes = []
        for impact_function in self.impact_functions:
            if_exposure_layer_mode = impact_function.metadata().\
                available_exposure_layer_mode(
                    exposure_key, exposure_geometry_key)
            if if_exposure_layer_mode:
                add_to_list(layer_modes, if_exposure_layer_mode)

        return layer_modes

    def hazard_additional_keywords(
            self, layer_mode_key=None, layer_geometry_key=None,
            hazard_category_key=None, hazard_key=None):
        """Return additional_keywords for hazard.

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :param hazard_key: The hazard key
        :type hazard_key: str

        :returns: List of additional keywords
        :rtype: list
        """
        additional_keywords = []
        for impact_function in self.impact_functions:
            if_additional_keywords = impact_function.metadata().\
                hazard_additional_keywords(
                    layer_mode_key=layer_mode_key,
                    layer_geometry_key=layer_geometry_key,
                    hazard_category_key=hazard_category_key,
                    hazard_key=hazard_key)
            if if_additional_keywords:
                add_to_list(additional_keywords, if_additional_keywords)

        return additional_keywords

    def exposure_additional_keywords(
            self, layer_mode_key=None, layer_geometry_key=None,
            exposure_key=None):
        """Return additional_keywords for exposure.

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param exposure_key: The hazard key
        :type exposure_key: str

        :returns: List of additional keywords
        :rtype: list
        """
        additional_keywords = []
        for impact_function in self.impact_functions:
            if_additional_keywords = impact_function.metadata().\
                exposure_additional_keywords(
                    layer_mode_key=layer_mode_key,
                    layer_geometry_key=layer_geometry_key,
                    exposure_key=exposure_key)
            if if_additional_keywords:
                add_to_list(additional_keywords, if_additional_keywords)

        return additional_keywords

    def exposure_class_fields(
            self, layer_mode_key=None, layer_geometry_key=None,
            exposure_key=None):
        """Return list of exposure class field.

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param exposure_key: The exposure key
        :type exposure_key: str

        :returns: List of exposure class field.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            if_exposure_class_field = impact_function.metadata(). \
                exposure_class_fields(
                    layer_mode_key=layer_mode_key,
                    layer_geometry_key=layer_geometry_key,
                    exposure_key=exposure_key)
            if if_exposure_class_field:
                add_to_list(result, if_exposure_class_field)

        return result
示例#33
0
class ImpactFunctionManager(object):
    """Class for managing metadata for all impact function.

    .. versionadded:: 2.1
    """
    def __init__(self):
        """Constructor."""
        # Singleton Registry to track all the registered Impact Functions
        self.registry = Registry()

    @property
    def impact_functions(self):
        """Return all registered impact functions."""
        return self.registry.impact_functions

    def get_instance(self, class_name):
        """Return an instance of an impact function given its class name.

        .. example::

            if_manager = ImpactFunctionManager()
            if_class_name = 'FloodBuildingImpactFunction'
            if =  if_manager.get_instance(if_class_name)

        :param class_name: The name of IF class.
        :type class_name: str

        :return: Impact function instance that matches the argument.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        return self.registry.get_instance(class_name)

    def get_class(self, class_name):
        """Return the class of an impact function given its class name.

        .. example::

            if_manager = ImpactFunctionManager()
            if_class_name = 'FloodBuildingImpactFunction'
            if_class =  if_manager.get_class(if_class_name)

        :param class_name: the name of IF class
        :type class_name: str

        :return: impact function class that matches the argument.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        return self.registry.get_class(class_name)

    def get(self, impact_function_id):
        """Return an instance of an impact function given its ID.

        This is a preferred way to get an instance of IF. IF should have a
        unique human readable ID in their metadata.

        .. example::

            if_manager = ImpactFunctionManager()
            if_id = 'FloodBuildingImpactFunction'
            if =  if_manager.get(if_id)

        :param impact_function_id: The ID of impact function in the metadata.
        :type impact_function_id: str

        :return An Impact function instance that has matched id.
        :rtype: safe.impact_functions.base.ImpactFunction
        """
        impact_functions = self.registry.filter_by_metadata(
            'id', impact_function_id)
        if len(impact_functions) == 0:
            raise Exception('Impact function with ID: %s not found' %
                            impact_function_id)
        elif len(impact_functions) > 1:
            raise Exception(
                'There are some Impact Functions that have the same ID: %s' %
                impact_function_id)
        return impact_functions[0].instance()

    def filter(self, hazard_metadata=None, exposure_metadata=None):
        """Get available impact functions from hazard and exposure metadata.

        Disabled impact function will not be loaded.

        .. example::

            if_manager = ImpactFunctionManager()
            hazard_metadata = {
                'subcategory': hazard_flood,
                'units': unit_wetdry,
                'layer_constraints': layer_vector_polygon
            }
            exposure_metadata = {
                'subcategory': exposure_structure,
                'units': unit_building_type_type,
                'layer_constraints': layer_vector_polygon
            }
            ifs =  if_manager.filter(hazard_metadata, exposure_metadata)

        :param hazard_metadata: The metadata of the hazard.
        :type hazard_metadata: dict

        :param exposure_metadata: The metadata of the exposure.
        :type exposure_metadata: dict
        """
        return self.registry.filter(hazard_metadata, exposure_metadata)

    def filter_by_keywords(self, hazard_keywords=None, exposure_keywords=None):
        """Get available impact functions from hazard and exposure keywords.

        Disabled impact function will not be loaded.

        .. example::

            if_manager = ImpactFunctionManager()
            hazard_keywords = {
                'subcategory': 'flood',
                'units': 'wetdry',
                'layer_type': 'vector',
                'data_type': 'polygon'
            }
            exposure_keywords = {
                'subcategory': 'structure',
                'units': 'building_type',
                'layer_type': 'vector',
                'data_type': 'polygon'
            }
            ifs =  if_manager.filter_by_keywords(hazard_keywords,
            exposure_keywords)

        :param hazard_keywords: The keywords of the hazard.
        :type hazard_keywords: dict

        :param exposure_keywords: The keywords of the exposure.
        :type exposure_keywords: dict
        """
        return self.registry.filter_by_keyword_string(hazard_keywords,
                                                      exposure_keywords)

    def filter_by_metadata(self, metadata_key, metadata_value):
        """Return IF classes given its metadata key and value.

        .. example::

            if_manager = ImpactFunctionManager()
            metadata_key = 'author'
            metadata_value = 'Akbar Gumbira'
            ifs =  if_manager.filter_by_metadata(metadata_key,
            metadata_value)

        :param metadata_key: The key of the metadata e.g 'id', 'name'
        :type metadata_key: str

        :param metadata_value: The value of the metadata, e.g for the key
            'id' the value is 'FloodNativePolygonExperimentalFunction'
        :type metadata_value: str, dict

        :return: Impact Function classes match the arguments
        :rtype: list
        """
        return self.registry.filter_by_metadata(metadata_key, metadata_value)

    @staticmethod
    def get_function_id(impact_function):
        """Get the ID of the impact function.

        :param impact_function: Class of an impact function
        :type impact_function: safe.impact_functions.base.ImpactFunction

        :returns: The ID of the impact function specified in its metadata.
        :rtype: str
        """
        return impact_function.metadata().as_dict().get('id', None)

    @staticmethod
    def get_function_title(impact_function):
        """Get title of the impact function.

        :param impact_function: Class of an impact function
        :type impact_function: safe.impact_functions.base.ImpactFunction

        :returns: The title of the impact function specified in its metadata.
        :rtype: str
        """
        return impact_function.metadata().as_dict().get('title', None)

    @staticmethod
    def get_function_name(impact_function):
        """Get the human readable name of the impact function.

        :param impact_function: Class of an impact function.
        :type impact_function: safe.impact_functions.base.ImpactFunction
        """
        return impact_function.metadata().as_dict().get('name', None)

    @staticmethod
    def get_function_type(impact_function):
        """Return the impact function type.

        :param impact_function: The impact function.
        :type impact_function: safe.impact_functions.base.ImpactFunction
        """
        return impact_function.function_type()

    def get_functions_for_hazard(self, hazard):
        """Return all function metadata that has hazard in their metadata.

        .. versionadded:: 2.2

        :param hazard: Dictionary that represent the hazard
        :type hazard: dict

        :return: List of impact function metadata.
        :rtype: list
        """
        impact_functions_metadata = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().has_hazard(hazard):
                impact_functions_metadata.append(
                    impact_function.metadata().as_dict())

        return impact_functions_metadata

    def purposes_for_layer(self, layer_geometry_key):
        """Get purposes of a layer geometry id.

        :param layer_geometry_key: The geometry id
        :type layer_geometry_key: str

        """
        layer_purposes = []
        for impact_function in self.impact_functions:
            if_layer_purposes = impact_function.metadata().purposes_for_layer(
                layer_geometry_key)
            if if_layer_purposes:
                add_to_list(layer_purposes, if_layer_purposes)

        return layer_purposes

    def hazard_categories_for_layer(self, layer_geometry_key, hazard_key=None):
        """Get hazard categories form layer_geometry_key

        :param layer_geometry_key: The geometry id
        :type layer_geometry_key: str

        :param hazard_key: The hazard key
        :type hazard_key: str

        :returns: List of hazard_categories
        :rtype: list
        """
        hazard_categories = []
        for impact_function in self.impact_functions:
            if_hazard_categories = impact_function.metadata()\
                .hazard_categories_for_layer(layer_geometry_key, hazard_key)
            if if_hazard_categories:
                add_to_list(hazard_categories, if_hazard_categories)

        return hazard_categories

    def hazards_for_layer(self, layer_geometry_key, hazard_category_key=None):
        """Get hazard categories form layer_geometry_key

        :param layer_geometry_key: The geometry id
        :type layer_geometry_key: str

        :param hazard_category_key: The hazard category
        :type hazard_category_key: str

        :returns: List of hazard
        :rtype: list
        """
        hazards = []
        for impact_function in self.impact_functions:
            if_hazards = impact_function.metadata().hazards_for_layer(
                layer_geometry_key, hazard_category_key)
            if if_hazards:
                add_to_list(hazards, if_hazards)

        return hazards

    def exposures_for_layer(self, layer_geometry_key):
        """Get hazard categories form layer_geometry_key

        :param layer_geometry_key: The geometry id
        :type layer_geometry_key: str

        :returns: List of hazard
        :rtype: list
        """
        exposures = []
        for impact_function in self.impact_functions:
            if_exposures = impact_function.metadata().exposures_for_layer(
                layer_geometry_key)
            if if_exposures:
                add_to_list(exposures, if_exposures)

        return exposures

    def exposure_units_for_layer(self, exposure_key, layer_geometry_key,
                                 layer_mode_key):
        """Get hazard categories form layer_geometry_key

        :param exposure_key: The exposure key
        :type exposure_key: str

        :param layer_geometry_key: The geometry key
        :type layer_geometry_key: str

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :returns: List of exposure unit
        :rtype: list
        """
        exposure_units = []
        for impact_function in self.impact_functions:
            if_exposure_units = impact_function.metadata().\
                exposure_units_for_layer(
                    exposure_key, layer_geometry_key, layer_mode_key)
            if if_exposure_units:
                add_to_list(exposure_units, if_exposure_units)

        return exposure_units

    def continuous_hazards_units_for_layer(self, hazard_key,
                                           layer_geometry_key, layer_mode_key,
                                           hazard_category_key):
        """Get continuous hazard units.
        :param hazard_key: The hazard key
        :type hazard_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of continuous hazard unit
        :rtype: list
        """
        continuous_hazards_units = []
        for impact_function in self.impact_functions:
            if_continuous_hazard_units = impact_function.metadata().\
                continuous_hazards_units_for_layer(
                    hazard_key, layer_geometry_key, layer_mode_key,
                    hazard_category_key)
            if if_continuous_hazard_units:
                add_to_list(continuous_hazards_units,
                            if_continuous_hazard_units)

        return continuous_hazards_units

    def vector_hazards_classifications_for_layer(self, hazard_key,
                                                 layer_geometry_key,
                                                 layer_mode_key,
                                                 hazard_category_key):
        """Get continuous hazard units.
        :param hazard_key: The hazard key
        :type hazard_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of vector_hazards_classifications
        :rtype: list
        """
        vector_hazards_classifications = []
        for impact_function in self.impact_functions:
            if_vector_hazards_classifications = impact_function.metadata().\
                vector_hazards_classifications_for_layer(
                    hazard_key, layer_geometry_key, layer_mode_key,
                    hazard_category_key)
            if if_vector_hazards_classifications:
                add_to_list(vector_hazards_classifications,
                            if_vector_hazards_classifications)

        return vector_hazards_classifications

    def raster_hazards_classifications_for_layer(self, hazard_key,
                                                 layer_geometry_key,
                                                 layer_mode_key,
                                                 hazard_category_key):
        """Get continuous hazard units.
        :param hazard_key: The hazard key
        :type hazard_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of raster_hazards_classifications
        :rtype: list
        """
        raster_hazards_classifications = []
        for impact_function in self.impact_functions:
            if_vector_hazards_classifications = impact_function.metadata().\
                raster_hazards_classifications_for_layer(
                    hazard_key, layer_geometry_key, layer_mode_key,
                    hazard_category_key)
            if if_vector_hazards_classifications:
                add_to_list(raster_hazards_classifications,
                            if_vector_hazards_classifications)

        return raster_hazards_classifications

    def available_hazards(self, hazard_category_key, ascending=True):
        """available_hazards from hazard_category_key

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :param ascending: Sort ascending or not.
        :type ascending: bool

        :returns: List of available hazards
        :rtype: list
        """

        hazards = []
        for impact_function in self.impact_functions:
            if_hazards = impact_function.metadata(). \
                available_hazards(hazard_category_key)
            if if_hazards:
                add_to_list(hazards, if_hazards)

        # make it sorted
        if ascending and hazards:
            hazards = sorted(hazards, key=lambda k: k['key'])

        return hazards

    def available_exposures(self, ascending=True):
        """Return a list of valid available exposures

        :param ascending: Sort ascending or not.
        :type ascending: bool

        :returns: A list of exposures full metadata.
        :rtype: list
        """

        exposures = []
        for impact_function in self.impact_functions:
            if_exposures = impact_function.metadata().available_exposures()
            if if_exposures:
                add_to_list(exposures, if_exposures)

        # make it sorted
        if ascending and exposures:
            exposures = sorted(exposures, key=lambda k: k['key'])

        return exposures

    def functions_for_constraint(self,
                                 hazard_key,
                                 exposure_key,
                                 hazard_geometry_key=None,
                                 exposure_geometry_key=None,
                                 hazard_mode_key=None,
                                 exposure_mode_key=None):
        """Obtain all functions that match with the constraints

        :param hazard_key: The hazard key
        :type hazard_key: str

        :param exposure_key: the exposure key
        :type exposure_key: str

        :param hazard_geometry_key: The hazard geometry key
        :type hazard_geometry_key: str

        :param exposure_geometry_key: The exposure geometry key
        :type exposure_geometry_key: str

        :param hazard_mode_key: The hazard mode key
        :type hazard_mode_key: str

        :param exposure_mode_key: The exposure mode key
        :type exposure_mode_key: str

        :returns: List of matched Impact Function
        :rtype: list
        """
        impact_functions = []
        for impact_function in self.impact_functions:
            if impact_function.metadata().is_function_for_constraint(
                    hazard_key, exposure_key, hazard_geometry_key,
                    exposure_geometry_key, hazard_mode_key, exposure_mode_key):
                impact_functions.append(impact_function.metadata().as_dict())

        return impact_functions

    def available_hazard_constraints(self, hazard_key, hazard_category_key):
        """Get hazard constraints for hazard_key and hazard_category_key

        :param hazard_key: The hazard key
        :type hazard_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of tuple of layer_mode and layer_geometry
        :rtype: list
        """
        hazard_constraints = []
        for impact_function in self.impact_functions:
            if_hazard_constraints = impact_function.metadata().\
                available_hazard_constraints(
                    hazard_key, hazard_category_key)
            if if_hazard_constraints:
                add_to_list(hazard_constraints, if_hazard_constraints)

        return hazard_constraints

    def available_exposure_constraints(self, exposure_key):
        """Get exposure constraints for exposure_key.

        :param exposure_key: The exposure key
        :type exposure_key: str

        :returns: List of tuple of layer_mode and layer_geometry
        :rtype: list
        """
        exposure_constraints = []
        for impact_function in self.impact_functions:
            if_exposure_constraints = impact_function.metadata(). \
                available_exposure_constraints(exposure_key)
            if if_exposure_constraints:
                add_to_list(exposure_constraints, if_exposure_constraints)

        return exposure_constraints

    def available_hazard_layer_modes(self, hazard_key, hazard_geometry_key,
                                     hazard_category_key):
        """Return all available layer_mode.

        :param hazard_key: The hazard key
        :type hazard_key: str

        :param hazard_geometry_key: The hazard geometry key
        :type hazard_geometry_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :returns: List of layer_mode
        :rtype: list
        """
        layer_modes = []
        for impact_function in self.impact_functions:
            if_hazard_layer_mode = impact_function.metadata().\
                available_hazard_layer_mode(
                    hazard_key, hazard_geometry_key, hazard_category_key)
            if if_hazard_layer_mode:
                add_to_list(layer_modes, if_hazard_layer_mode)

        return layer_modes

    def available_exposure_layer_modes(self, exposure_key,
                                       exposure_geometry_key):
        """Get exposure layer mode for exposure_key.

        :param exposure_key: The exposure key
        :type exposure_key: str

        :param exposure_geometry_key: The exposure geometry key
        :type exposure_geometry_key: str

        :returns: List of layer_mode
        :rtype: list
        """
        layer_modes = []
        for impact_function in self.impact_functions:
            if_exposure_layer_mode = impact_function.metadata().\
                available_exposure_layer_mode(
                    exposure_key, exposure_geometry_key)
            if if_exposure_layer_mode:
                add_to_list(layer_modes, if_exposure_layer_mode)

        return layer_modes

    def hazard_additional_keywords(self,
                                   layer_mode_key=None,
                                   layer_geometry_key=None,
                                   hazard_category_key=None,
                                   hazard_key=None):
        """Return additional_keywords for hazard.

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param hazard_category_key: The hazard category key
        :type hazard_category_key: str

        :param hazard_key: The hazard key
        :type hazard_key: str

        :returns: List of additional keywords
        :rtype: list
        """
        additional_keywords = []
        for impact_function in self.impact_functions:
            if_additional_keywords = impact_function.metadata().\
                hazard_additional_keywords(
                    layer_mode_key=layer_mode_key,
                    layer_geometry_key=layer_geometry_key,
                    hazard_category_key=hazard_category_key,
                    hazard_key=hazard_key)
            if if_additional_keywords:
                add_to_list(additional_keywords, if_additional_keywords)

        return additional_keywords

    def exposure_additional_keywords(self,
                                     layer_mode_key=None,
                                     layer_geometry_key=None,
                                     exposure_key=None):
        """Return additional_keywords for exposure.

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param exposure_key: The hazard key
        :type exposure_key: str

        :returns: List of additional keywords
        :rtype: list
        """
        additional_keywords = []
        for impact_function in self.impact_functions:
            if_additional_keywords = impact_function.metadata().\
                exposure_additional_keywords(
                    layer_mode_key=layer_mode_key,
                    layer_geometry_key=layer_geometry_key,
                    exposure_key=exposure_key)
            if if_additional_keywords:
                add_to_list(additional_keywords, if_additional_keywords)

        return additional_keywords

    def exposure_class_fields(self,
                              layer_mode_key=None,
                              layer_geometry_key=None,
                              exposure_key=None):
        """Return list of exposure class field.

        :param layer_mode_key: The layer mode key
        :type layer_mode_key: str

        :param layer_geometry_key: The layer geometry key
        :type layer_geometry_key: str

        :param exposure_key: The exposure key
        :type exposure_key: str

        :returns: List of exposure class field.
        :rtype: list
        """
        result = []
        for impact_function in self.impact_functions:
            if_exposure_class_field = impact_function.metadata(). \
                exposure_class_fields(
                    layer_mode_key=layer_mode_key,
                    layer_geometry_key=layer_geometry_key,
                    exposure_key=exposure_key)
            if if_exposure_class_field:
                add_to_list(result, if_exposure_class_field)

        return result
示例#34
0
 def __init__(self):
     """Constructor."""
     # Singleton Registry to track all the registered Impact Functions
     self.registry = Registry()