From 2c9c2b853a1540b1aaa42a2c3140ae744073331e Mon Sep 17 00:00:00 2001 From: Ismail Sunni Date: Mon, 19 Jan 2015 16:24:55 +0700 Subject: [PATCH] Add IF API get_available_exposures and get_functions_for_constraints. --- safe/gui/tools/wizard_dialog.py | 44 ++++---------- .../impact_function_manager.py | 60 +++++++++++++++++++ .../impact_function_metadata.py | 19 ++++++ .../inundation/flood_OSM_building_impact.py | 3 +- .../test/test_impact_function_manager.py | 58 +++++++++++++++++- .../test/test_impact_function_metadata.py | 27 +++++++++ 6 files changed, 175 insertions(+), 36 deletions(-) diff --git a/safe/gui/tools/wizard_dialog.py b/safe/gui/tools/wizard_dialog.py index 6a94338f18..6839ba0d05 100644 --- a/safe/gui/tools/wizard_dialog.py +++ b/safe/gui/tools/wizard_dialog.py @@ -231,29 +231,6 @@ elderly_ratio_default_key = DEFAULTS['ELDERLY_RATIO_KEY'] -def _tempapi_get_available_exposures(): - result = [] - for impact_function in ImpactFunctionManager().impact_functions: - for e in impact_function.Metadata.get_exposures(): - if e not in result: - result += [e] - return result - - -def _tempapi_get_functions_for_constraints(hazard, exposure, - hazard_constraint=None, - exposure_constraint=None): - result = [] - for f in ImpactFunctionManager().get_functions_for_hazard(hazard): - if f in ImpactFunctionManager().get_functions_for_exposure(exposure): - 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 += [f] - return result - - def get_question_text(constant): """Find a constant by name and return its value. @@ -1204,8 +1181,8 @@ def selected_functions_1(self): h_idx = self.tblFunctions1.column(selection[0]) e_idx = self.tblFunctions1.row(selection[0]) h = ImpactFunctionManager().get_available_hazards()[h_idx] - e = _tempapi_get_available_exposures()[e_idx] - functions = _tempapi_get_functions_for_constraints(h, e) + e = ImpactFunctionManager().get_available_exposures()[e_idx] + functions = ImpactFunctionManager().get_functions_for_constraint(h, e) return functions def selected_imfunc_constraints(self): @@ -1221,7 +1198,7 @@ def selected_imfunc_constraints(self): h_idx = self.tblFunctions1.column(selection[0]) e_idx = self.tblFunctions1.row(selection[0]) h = ImpactFunctionManager().get_available_hazards()[h_idx] - e = _tempapi_get_available_exposures()[e_idx] + e = ImpactFunctionManager().get_available_exposures()[e_idx] selection = self.tblFunctions2.selectedItems() if len(selection) != 1: @@ -1256,7 +1233,7 @@ def on_tblFunctions1_itemSelectionChanged(self): def set_widgets_step_fc_function_1(self): """Set widgets on the Impact Functions Table 1 tab.""" hazards = ImpactFunctionManager().get_available_hazards() - exposures = _tempapi_get_available_exposures() + exposures = ImpactFunctionManager().get_available_exposures() self.lblAvailableFunctions1.clear() self.tblFunctions1.setColumnCount(len(hazards)) @@ -1269,7 +1246,8 @@ def set_widgets_step_fc_function_1(self): for h in hazards: for e in exposures: item = QtGui.QTableWidgetItem() - functions = _tempapi_get_functions_for_constraints(h, e) + functions = ImpactFunctionManager( + ).get_functions_for_constraint(h, e) if len(functions): bgcolor = QtGui.QColor(120, 255, 120) else: @@ -1292,7 +1270,8 @@ def selected_functions_2(self): :rtype: list, None """ h, e, hc, ec = self.selected_imfunc_constraints() - functions = _tempapi_get_functions_for_constraints(h, e, hc, ec) + functions = ImpactFunctionManager().get_functions_for_constraint( + h, e, hc, ec) return functions # prevents actions being handled twice @@ -1325,8 +1304,8 @@ def set_widgets_step_fc_function_2(self): for row in range(len(datatypes)): hc = self.available_constraints()[col] ec = self.available_constraints()[row] - functions = _tempapi_get_functions_for_constraints(h, e, - hc, ec) + functions = ImpactFunctionManager( + ).get_functions_for_constraint(h, e, hc, ec) item = QtGui.QTableWidgetItem() if len(functions): @@ -1397,7 +1376,8 @@ def set_widgets_step_fc_function_3(self): self.lblDescribeFunction.setText('') h, e, hc, ec = self.selected_imfunc_constraints() - functions = _tempapi_get_functions_for_constraints(h, e, hc, ec) + functions = ImpactFunctionManager().get_functions_for_constraint( + h, e, hc, ec) for f in functions: item = QtGui.QListWidgetItem(self.lstFunctions) item.setText(f['name']) diff --git a/safe/impact_functions/impact_function_manager.py b/safe/impact_functions/impact_function_manager.py index 77e9680720..36e20a8256 100644 --- a/safe/impact_functions/impact_function_manager.py +++ b/safe/impact_functions/impact_function_manager.py @@ -339,6 +339,38 @@ def get_functions_for_hazard_id(self, hazard_id): 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. @@ -376,3 +408,31 @@ def get_functions_for_exposure_id(self, exposure_id): impact_function.Metadata.get_metadata()) return impact_functions_metadata + + def get_functions_for_constraint( + self, + hazard, + exposure, + hazard_constraint=None, + exposure_constraint=None): + """ + + :param hazard: + :param exposure: + :param hazard_constraint: + :param exposure_constraint: + :return: + """ + result = [] + if_hazard = self.get_functions_for_hazard(hazard) + if_exposure = self.get_functions_for_exposure(exposure) + + for f in if_hazard: + if f in if_exposure: + 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 \ No newline at end of file diff --git a/safe/impact_functions/impact_function_metadata.py b/safe/impact_functions/impact_function_metadata.py index 1a310dc29e..d77049a195 100644 --- a/safe/impact_functions/impact_function_metadata.py +++ b/safe/impact_functions/impact_function_metadata.py @@ -524,3 +524,22 @@ def has_exposure_id(cls, exposure_id): exposures = cls.get_exposures() exposure_ids = [exposure['id'] for exposure in exposures] return exposure_id in exposure_ids + + @classmethod + def get_hazard_layer_constraint(cls): + """Helper function to get the constraints for hazard layer. + + :return: List of layer constraint of hazard layer. + :rtype: list + """ + return cls.get_metadata()['categories']['hazard']['layer_constraints'] + + @classmethod + def get_exposure_layer_constraint(cls): + """Helper function to get the constraints for exposure layer. + + :return: List of layer constraint of exposure layer. + :rtype: list + """ + return cls.get_metadata()[ + 'categories']['exposure']['layer_constraints'] \ No newline at end of file diff --git a/safe/impact_functions/inundation/flood_OSM_building_impact.py b/safe/impact_functions/inundation/flood_OSM_building_impact.py index 1c68bd18e7..417a4b0e88 100644 --- a/safe/impact_functions/inundation/flood_OSM_building_impact.py +++ b/safe/impact_functions/inundation/flood_OSM_building_impact.py @@ -112,7 +112,8 @@ def get_metadata(): unit_building_generic], 'layer_constraints': [ layer_vector_polygon, - layer_vector_point] + layer_vector_point + ] } } } diff --git a/safe/impact_functions/test/test_impact_function_manager.py b/safe/impact_functions/test/test_impact_function_manager.py index b9018f2577..6b4d52012d 100644 --- a/safe/impact_functions/test/test_impact_function_manager.py +++ b/safe/impact_functions/test/test_impact_function_manager.py @@ -29,12 +29,12 @@ VolcanoBuildingImpact) from safe.impact_functions.volcanic. \ volcano_population_evacuation_polygon_hazard import ( - VolcanoPolygonHazardPopulation) + VolcanoPolygonHazardPopulation) from safe.impact_functions.generic.categorised_hazard_population import ( CategorisedHazardPopulationImpactFunction) from safe.impact_functions.generic.categorical_hazard_building import ( CategoricalHazardBuildingImpactFunction) -from safe.impact_functions.generic.categorical_hazard_population import ( +from safe.impact_functions.generic.categorical_hazard_population import ( CategoricalHazardPopulationImpactFunction) from safe.metadata import ( @@ -58,7 +58,9 @@ hazard_generic, unit_building_generic, unit_categorised, - hazard_all) + hazard_all, + layer_vector_polygon, + layer_vector_line) class TestImpactFunctionManager(unittest.TestCase): @@ -295,6 +297,24 @@ def test_get_functions_for_hazard_id(self): message = ('I expect %s but I got %s.' % (expected_result, result)) self.assertItemsEqual(result, expected_result, message) + def test_get_available_exposures(self): + """Test get_available_exposures API.""" + impact_function_manager = ImpactFunctionManager() + + result = impact_function_manager.get_available_exposures() + expected_result = [ + exposure_population, + exposure_road, + exposure_structure] + message = ('I expect %s but I got %s.' % (expected_result, result)) + self.assertItemsEqual(result, expected_result, message) + + impact_function = EarthquakeBuildingImpactFunction() + result = impact_function_manager.get_available_exposures(impact_function) + expected_result = [exposure_structure] + message = ('I expect %s but I got %s.' % (expected_result, result)) + self.assertItemsEqual(result, expected_result, message) + def test_get_functions_for_exposure(self): """Test get_functions_for_exposure API.""" impact_function_manager = ImpactFunctionManager() @@ -323,6 +343,38 @@ def test_get_functions_for_exposure_id(self): message = ('I expect %s but I got %s.' % (expected_result, result)) self.assertItemsEqual(result, expected_result, message) + def test_get_functions_for_constraint(self): + """Test get_functions_for_constraint.""" + impact_function_manager = ImpactFunctionManager() + hazard = hazard_earthquake + exposure = exposure_structure + + expected_result = [ + EarthquakeBuildingImpactFunction.Metadata.get_metadata(), + CategoricalHazardBuildingImpactFunction.Metadata.get_metadata()] + result = impact_function_manager.get_functions_for_constraint( + hazard, exposure) + message = ('I expect %s but I got %s.' % (expected_result, result)) + self.assertItemsEqual(expected_result, result, message) + + hazard_constraint = layer_vector_polygon + exposure_constraint = None + + expected_result = [ + EarthquakeBuildingImpactFunction.Metadata.get_metadata()] + result = impact_function_manager.get_functions_for_constraint( + hazard, exposure, hazard_constraint, exposure_constraint) + message = ('I expect %s but I got %s.' % (expected_result, result)) + self.assertItemsEqual(expected_result, result, message) + + hazard_constraint = layer_vector_polygon + exposure_constraint = layer_vector_line + + expected_result = [] + result = impact_function_manager.get_functions_for_constraint( + hazard, exposure, hazard_constraint, exposure_constraint) + message = ('I expect %s but I got %s.' % (expected_result, result)) + self.assertItemsEqual(expected_result, result, message) if __name__ == '__main__': unittest.main() diff --git a/safe/impact_functions/test/test_impact_function_metadata.py b/safe/impact_functions/test/test_impact_function_metadata.py index 0aff931f91..091dbd9e3f 100644 --- a/safe/impact_functions/test/test_impact_function_metadata.py +++ b/safe/impact_functions/test/test_impact_function_metadata.py @@ -351,6 +351,33 @@ def test_has_exposure_id(self): message = ('I expect %s but I got %s.' % (expected_result, result)) self.assertEqual(result, expected_result, message) + def test_get_hazard_layer_constraint(self): + """Test for get_hazard_layer_constraint.""" + impact_function = FloodBuildingImpactFunction() + expected_layer_constraint = [ + layer_vector_polygon, + layer_raster_numeric + ] + layer_constraints \ + = impact_function.Metadata.get_hazard_layer_constraint() + message = 'Expected %s but got %s' % ( + expected_layer_constraint, layer_constraints) + self.assertItemsEqual( + expected_layer_constraint, layer_constraints, message) + + def test_get_exposure_layer_constraint(self): + """Test for get_exposure_layer_constraint.""" + impact_function = FloodBuildingImpactFunction() + expected_layer_constraint = [ + layer_vector_polygon, + layer_vector_point + ] + layer_constraints \ + = impact_function.Metadata.get_exposure_layer_constraint() + message = 'Expected %s but got %s' % ( + expected_layer_constraint, layer_constraints) + self.assertItemsEqual( + expected_layer_constraint, layer_constraints, message) if __name__ == '__main__': unittest.main()