Source code for safe.impact_functions.generic.categorised_hazard_building_impact

from safe.impact_functions.core import (FunctionProvider,
                                        get_hazard_layer,
                                        get_exposure_layer,
                                        get_question,
                                        format_int)
from safe.storage.vector import Vector
from safe.common.utilities import ugettext as tr
from safe.common.tables import Table, TableRow
from safe.engine.interpolation import assign_hazard_values_to_exposure_data


#FIXME: need to normalise all raster data Ole/Kristy
[docs]class CategorisedHazardBuildingImpactFunction(FunctionProvider): """Impact plugin for categorising hazard impact on building data :author The Author :rating The Rating :detail The Detail :param requires category=='hazard' and \ unit=='normalised' and \ layertype=='raster' :param requires category=='exposure' and \ subcategory=='structure' and \ layertype=='vector' :citation citation1 :citation citation2 \ next citation2 """ target_field = 'ICLASS' title = tr('Be affected')
[docs] def run(self, layers): """Impact plugin for hazard impact """ # Extract data H = get_hazard_layer(layers) # Value E = get_exposure_layer(layers) # Building locations question = get_question(H.get_name(), E.get_name(), self) # Interpolate hazard level to building locations H = assign_hazard_values_to_exposure_data(H, E, attribute_name='hazard_lev', mode='constant') # Extract relevant numerical data coordinates = H.get_geometry() category = H.get_data() N = len(category) # List attributes to carry forward to result layer #attributes = E.get_attribute_names() # Calculate building impact according to guidelines count2 = 0 count1 = 0 count0 = 0 building_impact = [] for i in range(N): # Get category value val = float(category[i]['hazard_lev']) # Classify buildings according to value ## if val >= 2.0 / 3: ## affected = 2 ## count2 += 1 ## elif 1.0 / 3 <= val < 2.0 / 3: ## affected = 1 ## count1 += 1 ## else: ## affected = 0 ## count0 += 1 ## FIXME it would be good if the affected were words not numbers ## FIXME need to read hazard layer and see category or keyword if val == 3: affected = 3 count2 += 1 elif val == 2: affected = 2 count1 += 1 elif val == 1: affected = 1 count0 += 1 else: affected = 'None' # Collect depth and calculated damage result_dict = {self.target_field: affected, 'CATEGORY': val} # Record result for this feature building_impact.append(result_dict) # Create impact report # Generate impact summary table_body = [question, TableRow([tr('Category'), tr('Affected')], header=True), TableRow([tr('High'), format_int(count2)]), TableRow([tr('Medium'), format_int(count1)]), TableRow([tr('Low'), format_int(count0)]), TableRow([tr('All'), format_int(N)])] table_body.append(TableRow(tr('Notes'), header=True)) table_body.append(tr('Categorised hazard has only 3' ' classes, high, medium and low.')) impact_summary = Table(table_body).toNewlineFreeString() impact_table = impact_summary map_title = tr('Categorised hazard impact on buildings') #FIXME it would be great to do categorized rather than grduated # Create style style_classes = [dict(label=tr('Low'), min=1, max=1, colour='#1EFC7C', transparency=0, size=1), dict(label=tr('Medium'), min=2, max=2, colour='#FFA500', transparency=0, size=1), dict(label=tr('High'), min=3, max=3, colour='#F31A1C', transparency=0, size=1)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return name = 'Buildings Affected' V = Vector(data=building_impact, projection=E.get_projection(), geometry=coordinates, geometry_type=E.geometry_type, keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title, 'target_field': self.target_field}, name=name, style_info=style_info) return V