def run(self, layers): """Risk plugin for volcano population evacuation Input layers: List of layers expected to contain H: Vector polygon layer of volcano impact zones P: Raster layer of population data on the same grid as H Counts number of people exposed to volcano event. Return Map of population exposed to the volcano hazard zone. Table with number of people evacuated and supplies required. """ # Identify hazard and exposure layers H = get_hazard_layer(layers) # Flood inundation E = get_exposure_layer(layers) question = get_question(H.get_name(), E.get_name(), self) # Input checks if not H.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % H.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. ' 'I got %s with layer ' 'type %s' % (H.get_name(), H.get_geometry_name())) if not (H.is_polygon_data or H.is_point_data): raise Exception(msg) if H.is_point_data: # Use concentric circles radii = self.parameters['distance [km]'] centers = H.get_geometry() attributes = H.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters H = make_circular_polygon(centers, rad_m, attributes=attributes) # NOTE (Sunni) : I commented out this one because there will be # a permission problem on windows #H.write_to_file('Evac_zones_%s.shp' % str(radii)) # To check category_title = 'Radius' category_header = tr('Distance [km]') category_names = radii name_attribute = 'NAME' # As in e.g. the Smithsonian dataset else: # Use hazard map category_title = 'KRB' category_header = tr('Category') # FIXME (Ole): Change to English and use translation system category_names = ['Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I'] name_attribute = 'GUNUNG' # As in e.g. BNPB hazard map attributes = H.get_data() # Get names of volcanos considered if name_attribute in H.get_attribute_names(): D = {} for att in H.get_data(): # Run through all polygons and get unique names D[att[name_attribute]] = None volcano_names = '' for name in D: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') if not category_title in H.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (H.get_name(), category_title)) raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(H, E, attribute_name='population') # Initialise attributes of output dataset with all attributes # from input polygon and a population count of zero new_attributes = H.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count affected population per polygon and total evacuated = 0 for attr in P.get_data(): # Get population at this location pop = float(attr['population']) # Update population count for associated polygon poly_id = attr['polygon_id'] new_attributes[poly_id][self.target_field] += pop # Update population count for each category cat = new_attributes[poly_id][category_title] categories[cat] += pop # Count totals total = int(numpy.sum(E.get_data(nan=0))) # Don't show digits less than a 1000 total = round_thousand(total) # Count number and cumulative for each zone cum = 0 pops = {} cums = {} for name in category_names: if category_title == 'Radius': key = name * 1000 # Convert to meters else: key = name pop = int(categories[key]) pop = round_thousand(pop) cum += pop cum = round_thousand(cum) pops[name] = pop cums[name] = cum # Use final accumulation as total number needing evac evacuated = cum # Calculate estimated needs based on BNPB Perka # 7/2008 minimum bantuan # FIXME (Ole): Refactor into one function to be shared rice = int(evacuated * 2.8) drinking_water = int(evacuated * 17.5) water = int(evacuated * 67) family_kits = int(evacuated / 5) toilets = int(evacuated / 20) # Generate impact report for the pdf map blank_cell = '' table_body = [question, TableRow([tr('Volcanos considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([tr('People needing evacuation'), '%s' % format_int(evacuated), blank_cell], header=True), TableRow([category_header, tr('Total'), tr('Cumulative')], header=True)] for name in category_names: table_body.append(TableRow([name, format_int(pops[name]), format_int(cums[name])])) table_body.extend([TableRow(tr('Map shows population affected in ' 'each of volcano hazard polygons.')), TableRow([tr('Needs per week'), tr('Total'), blank_cell], header=True), [tr('Rice [kg]'), format_int(rice), blank_cell], [tr('Drinking Water [l]'), format_int(drinking_water), blank_cell], [tr('Clean Water [l]'), format_int(water), blank_cell], [tr('Family Kits'), format_int(family_kits), blank_cell], [tr('Toilets'), format_int(toilets), blank_cell]]) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([TableRow(tr('Notes'), header=True), tr('Total population %s in the exposure layer') % format_int(total), tr('People need evacuation if they are within the ' 'volcanic hazard zones.')]) impact_summary = Table(table_body).toNewlineFreeString() map_title = tr('People affected by volcanic hazard zone') # Define classes for legend for flooded population counts colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] population_counts = [x[self.target_field] for x in new_attributes] cls = [0] + numpy.linspace(1, max(population_counts), len(colours)).tolist() # Define style info for output polygons showing population counts style_classes = [] for i, colour in enumerate(colours): lo = cls[i] hi = cls[i + 1] if i == 0: label = tr('0') else: label = tr('%i - %i') % (lo, hi) entry = dict(label=label, colour=colour, min=lo, max=hi, transparency=50, size=1) style_classes.append(entry) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, legend_title=tr('Population Count')) # Create vector layer and return V = Vector(data=new_attributes, projection=H.get_projection(), geometry=H.get_geometry(as_geometry_objects=True), name=tr('Population affected by volcanic hazard zone'), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title, 'target_field': self.target_field}, style_info=style_info) return V
def run(self, layers): """Risk plugin for volcano hazard on building/structure Input layers: List of layers expected to contain my_hazard: Hazard layer of volcano my_exposure: Vector layer of structure data on the same grid as my_hazard Counts number of building exposed to each volcano hazard zones. Return Map of building exposed to volcanic hazard zones Table with number of buildings affected """ # Identify hazard and exposure layers my_hazard = get_hazard_layer(layers) # Volcano hazard layer my_exposure = get_exposure_layer(layers) is_point_data = False question = get_question(my_hazard.get_name(), my_exposure.get_name(), self) # Input checks if not my_hazard.is_vector: msg = "Input hazard %s was not a vector layer as expected " % my_hazard.get_name() raise Exception(msg) msg = "Input hazard must be a polygon or point layer. I got %s " "with layer type %s" % ( my_hazard.get_name(), my_hazard.get_geometry_name(), ) if not (my_hazard.is_polygon_data or my_hazard.is_point_data): raise Exception(msg) if my_hazard.is_point_data: # Use concentric circles radii = self.parameters["distances [km]"] is_point_data = True centers = my_hazard.get_geometry() attributes = my_hazard.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters Z = make_circular_polygon(centers, rad_m, attributes=attributes) # To check category_title = "Radius" my_hazard = Z category_names = rad_m name_attribute = "NAME" # As in e.g. the Smithsonian dataset else: # Use hazard map category_title = "KRB" # FIXME (Ole): Change to English and use translation system category_names = ["Kawasan Rawan Bencana III", "Kawasan Rawan Bencana II", "Kawasan Rawan Bencana I"] name_attribute = "GUNUNG" # As in e.g. BNPB hazard map # Get names of volcanos considered if name_attribute in my_hazard.get_attribute_names(): D = {} for att in my_hazard.get_data(): # Run through all polygons and get unique names D[att[name_attribute]] = None volcano_names = "" for name in D: volcano_names += "%s, " % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr("Not specified in data") if not category_title in my_hazard.get_attribute_names(): msg = "Hazard data %s did not contain expected " "attribute %s " % (my_hazard.get_name(), category_title) # noinspection PyExceptionInherit raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(my_hazard, my_exposure) # Initialise attributes of output dataset with all attributes # from input polygon and a building count of zero new_attributes = my_hazard.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count impacted building per polygon and total for attr in P.get_data(): # Update building count for associated polygon poly_id = attr["polygon_id"] if poly_id is not None: new_attributes[poly_id][self.target_field] += 1 # Update building count for each category cat = new_attributes[poly_id][category_title] categories[cat] += 1 # Count totals total = len(my_exposure) # Generate simple impact report blank_cell = "" table_body = [ question, TableRow([tr("Volcanos considered"), "%s" % volcano_names, blank_cell], header=True), TableRow([tr("Distance [km]"), tr("Total"), tr("Cumulative")], header=True), ] cum = 0 for name in category_names: # prevent key error count = categories.get(name, 0) cum += count if is_point_data: name = int(name) / 1000 table_body.append(TableRow([name, format_int(count), format_int(cum)])) table_body.append(TableRow(tr("Map shows buildings affected in " "each of volcano hazard polygons."))) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend( [ TableRow(tr("Notes"), header=True), tr("Total number of buildings %s in the viewable " "area") % format_int(total), tr("Only buildings available in OpenStreetMap " "are considered."), ] ) impact_summary = Table(table_body).toNewlineFreeString() building_counts = [x[self.target_field] for x in new_attributes] if max(building_counts) == 0 == min(building_counts): table_body = [ question, TableRow([tr("Number of buildings affected"), "%s" % format_int(cum), blank_cell], header=True), ] my_message = Table(table_body).toNewlineFreeString() raise ZeroImpactException(my_message) # Create style colours = ["#FFFFFF", "#38A800", "#79C900", "#CEED00", "#FFCC00", "#FF6600", "#FF0000", "#7A0000"] classes = create_classes(building_counts, len(colours)) interval_classes = humanize_class(classes) style_classes = [] for i in xrange(len(colours)): style_class = dict() style_class["label"] = create_label(interval_classes[i]) if i == 0: transparency = 100 style_class["min"] = 0 else: transparency = 30 style_class["min"] = classes[i - 1] style_class["transparency"] = transparency style_class["colour"] = colours[i] style_class["max"] = classes[i] style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, style_type="graduatedSymbol") # For printing map purpose map_title = tr("Buildings affected by volcanic hazard zone") legend_notes = tr("Thousand separator is represented by %s" % get_thousand_separator()) legend_units = tr("(building)") legend_title = tr("Building count") # Create vector layer and return V = Vector( data=new_attributes, projection=my_hazard.get_projection(), geometry=my_hazard.get_geometry(as_geometry_objects=True), name=tr("Buildings affected by volcanic hazard zone"), keywords={ "impact_summary": impact_summary, "impact_table": impact_table, "target_field": self.target_field, "map_title": map_title, "legend_notes": legend_notes, "legend_units": legend_units, "legend_title": legend_title, }, style_info=style_info, ) return V
from safe.engine.interpolation import make_circular_polygon from safe.storage.core import read_layer H = read_layer('/data_area/InaSAFE/public_data/hazard/Marapi.shp') print H.get_geometry() # Generate evacuation circle (as a polygon): radius = 3000 center = H.get_geometry()[0] Z = make_circular_polygon(center, radius) Z.write_to_file('Marapi_evac_zone_%im.shp' % radius)
def run(self, layers): """Risk plugin for volcano hazard on building/structure Input layers: List of layers expected to contain my_hazard: Hazard layer of volcano my_exposure: Vector layer of structure data on the same grid as my_hazard Counts number of building exposed to each volcano hazard zones. Return Map of building exposed to volcanic hazard zones Table with number of buildings affected """ # Identify hazard and exposure layers my_hazard = get_hazard_layer(layers) # Volcano hazard layer my_exposure = get_exposure_layer(layers) is_point_data = False question = get_question(my_hazard.get_name(), my_exposure.get_name(), self) # Input checks if not my_hazard.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % my_hazard.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. I got %s ' 'with layer type %s' % (my_hazard.get_name(), my_hazard.get_geometry_name())) if not (my_hazard.is_polygon_data or my_hazard.is_point_data): raise Exception(msg) if my_hazard.is_point_data: # Use concentric circles radii = self.parameters['distances [km]'] is_point_data = True centers = my_hazard.get_geometry() attributes = my_hazard.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters Z = make_circular_polygon(centers, rad_m, attributes=attributes) # To check category_title = 'Radius' my_hazard = Z category_names = rad_m name_attribute = 'NAME' # As in e.g. the Smithsonian dataset else: # Use hazard map category_title = 'KRB' # FIXME (Ole): Change to English and use translation system category_names = ['Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I'] name_attribute = 'GUNUNG' # As in e.g. BNPB hazard map # Get names of volcanos considered if name_attribute in my_hazard.get_attribute_names(): D = {} for att in my_hazard.get_data(): # Run through all polygons and get unique names D[att[name_attribute]] = None volcano_names = '' for name in D: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') if not category_title in my_hazard.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (my_hazard.get_name(), category_title)) raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(my_hazard, my_exposure) # Initialise attributes of output dataset with all attributes # from input polygon and a building count of zero new_attributes = my_hazard.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count impacted building per polygon and total for attr in P.get_data(): # Update building count for associated polygon poly_id = attr['polygon_id'] if poly_id is not None: new_attributes[poly_id][self.target_field] += 1 # Update building count for each category cat = new_attributes[poly_id][category_title] categories[cat] += 1 # Count totals total = len(my_exposure) # Generate simple impact report blank_cell = '' table_body = [question, TableRow([tr('Volcanos considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([tr('Distance [km]'), tr('Total'), tr('Cumulative')], header=True)] cum = 0 for name in category_names: # prevent key error count = categories.get(name, 0) cum += count if is_point_data: name = int(name) / 1000 table_body.append(TableRow([name, format_int(count), format_int(cum)])) table_body.append(TableRow(tr('Map shows buildings affected in ' 'each of volcano hazard polygons.'))) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([TableRow(tr('Notes'), header=True), tr('Total number of buildings %s in the viewable ' 'area') % format_int(total), tr('Only buildings available in OpenStreetMap ' 'are considered.')]) impact_summary = Table(table_body).toNewlineFreeString() map_title = tr('Buildings affected by volcanic hazard zone') # Create style colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] building_counts = [x[self.target_field] for x in new_attributes] classes = create_classes(building_counts, len(colours)) interval_classes = humanize_class(classes) style_classes = [] for i in xrange(len(colours)): style_class = dict() style_class['label'] = create_label(interval_classes[i]) if i == 0: transparency = 100 style_class['min'] = 0 else: transparency = 30 style_class['min'] = classes[i - 1] style_class['transparency'] = transparency style_class['colour'] = colours[i] style_class['max'] = classes[i] style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, style_type='graduatedSymbol') # For printing map purpose map_title = tr('Building affected by volcanic hazard zone') legend_notes = tr('Thousand separator is represented by \'.\'') legend_units = tr('(building)') legend_title = tr('Building count') # Create vector layer and return V = Vector(data=new_attributes, projection=my_hazard.get_projection(), geometry=my_hazard.get_geometry(as_geometry_objects=True), name=tr('Buildings affected by volcanic hazard zone'), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'target_field': self.target_field, 'map_title': map_title, 'legend_notes': legend_notes, 'legend_units': legend_units, 'legend_title': legend_title}, style_info=style_info) return V
def run(self, layers): """Risk plugin for volcano hazard on building/structure Input layers: List of layers expected to contain my_hazard: Hazard layer of volcano my_exposure: Vector layer of structure data on the same grid as my_hazard Counts number of building exposed to each volcano hazard zones. Return Map of building exposed to volcanic hazard zones Table with number of buildings affected """ # Identify hazard and exposure layers my_hazard = get_hazard_layer(layers) # Volcano hazard layer my_exposure = get_exposure_layer(layers) is_point_data = False question = get_question(my_hazard.get_name(), my_exposure.get_name(), self) # Input checks if not my_hazard.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % my_hazard.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. I got %s ' 'with layer type %s' % (my_hazard.get_name(), my_hazard.get_geometry_name())) if not (my_hazard.is_polygon_data or my_hazard.is_point_data): raise Exception(msg) if my_hazard.is_point_data: # Use concentric circles radii = self.parameters['distances [km]'] is_point_data = True centers = my_hazard.get_geometry() attributes = my_hazard.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters Z = make_circular_polygon(centers, rad_m, attributes=attributes) # To check category_title = 'Radius' my_hazard = Z category_names = rad_m name_attribute = 'NAME' # As in e.g. the Smithsonian dataset else: # Use hazard map category_title = 'KRB' # FIXME (Ole): Change to English and use translation system category_names = [ 'Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I' ] name_attribute = 'GUNUNG' # As in e.g. BNPB hazard map # Get names of volcanos considered if name_attribute in my_hazard.get_attribute_names(): D = {} for att in my_hazard.get_data(): # Run through all polygons and get unique names D[att[name_attribute]] = None volcano_names = '' for name in D: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') if not category_title in my_hazard.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (my_hazard.get_name(), category_title)) # noinspection PyExceptionInherit raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(my_hazard, my_exposure) # Initialise attributes of output dataset with all attributes # from input polygon and a building count of zero new_attributes = my_hazard.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count impacted building per polygon and total for attr in P.get_data(): # Update building count for associated polygon poly_id = attr['polygon_id'] if poly_id is not None: new_attributes[poly_id][self.target_field] += 1 # Update building count for each category cat = new_attributes[poly_id][category_title] categories[cat] += 1 # Count totals total = len(my_exposure) # Generate simple impact report blank_cell = '' table_body = [ question, TableRow( [tr('Volcanos considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([tr('Distance [km]'), tr('Total'), tr('Cumulative')], header=True) ] cum = 0 for name in category_names: # prevent key error count = categories.get(name, 0) cum += count if is_point_data: name = int(name) / 1000 table_body.append( TableRow([name, format_int(count), format_int(cum)])) table_body.append( TableRow( tr('Map shows buildings affected in ' 'each of volcano hazard polygons.'))) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([ TableRow(tr('Notes'), header=True), tr('Total number of buildings %s in the viewable ' 'area') % format_int(total), tr('Only buildings available in OpenStreetMap ' 'are considered.') ]) impact_summary = Table(table_body).toNewlineFreeString() building_counts = [x[self.target_field] for x in new_attributes] if max(building_counts) == 0 == min(building_counts): table_body = [ question, TableRow([ tr('Number of buildings affected'), '%s' % format_int(cum), blank_cell ], header=True) ] my_message = Table(table_body).toNewlineFreeString() raise ZeroImpactException(my_message) # Create style colours = [ '#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000' ] classes = create_classes(building_counts, len(colours)) interval_classes = humanize_class(classes) style_classes = [] for i in xrange(len(colours)): style_class = dict() style_class['label'] = create_label(interval_classes[i]) if i == 0: transparency = 100 style_class['min'] = 0 else: transparency = 30 style_class['min'] = classes[i - 1] style_class['transparency'] = transparency style_class['colour'] = colours[i] style_class['max'] = classes[i] style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, style_type='graduatedSymbol') # For printing map purpose map_title = tr('Buildings affected by volcanic hazard zone') legend_notes = tr('Thousand separator is represented by %s' % get_thousand_separator()) legend_units = tr('(building)') legend_title = tr('Building count') # Create vector layer and return V = Vector(data=new_attributes, projection=my_hazard.get_projection(), geometry=my_hazard.get_geometry(as_geometry_objects=True), name=tr('Buildings affected by volcanic hazard zone'), keywords={ 'impact_summary': impact_summary, 'impact_table': impact_table, 'target_field': self.target_field, 'map_title': map_title, 'legend_notes': legend_notes, 'legend_units': legend_units, 'legend_title': legend_title }, style_info=style_info) return V
def run(self, layers): """Risk plugin for flood population evacuation Input layers: List of layers expected to contain H: Raster layer of volcano depth P: Raster layer of population data on the same grid as H Counts number of people exposed to flood levels exceeding specified threshold. Return Map of population exposed to flood levels exceeding the threshold Table with number of people evacuated and supplies required """ # Identify hazard and exposure layers H = get_hazard_layer(layers) # Flood inundation E = get_exposure_layer(layers) question = get_question(H.get_name(), E.get_name(), self) # Input checks if not H.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % H.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. ' 'I got %s with layer ' 'type %s' % (H.get_name(), H.get_geometry_name())) if not (H.is_polygon_data or H.is_point_data): raise Exception(msg) if H.is_point_data: # Use concentric circles radii = self.parameters['R [km]'] centers = H.get_geometry() attributes = H.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters H = make_circular_polygon(centers, rad_m, attributes=attributes) #H.write_to_file('Evac_zones_%s.shp' % str(radii)) # To check category_title = 'Radius' category_header = tr('Distance [km]') category_names = radii name_attribute = 'NAME' # As in e.g. the Smithsonian dataset else: # Use hazard map category_title = 'KRB' category_header = tr('Category') # FIXME (Ole): Change to English and use translation system category_names = [ 'Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I' ] name_attribute = 'GUNUNG' # As in e.g. BNPB hazard map attributes = H.get_data() # Get names of volcanos considered if name_attribute in H.get_attribute_names(): D = {} for att in H.get_data(): # Run through all polygons and get unique names D[att[name_attribute]] = None volcano_names = '' for name in D: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') if not category_title in H.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (H.get_name(), category_title)) raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(H, E, attribute_name='population') # Initialise attributes of output dataset with all attributes # from input polygon and a population count of zero new_attributes = H.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count affected population per polygon and total evacuated = 0 for attr in P.get_data(): # Get population at this location pop = float(attr['population']) # Update population count for associated polygon poly_id = attr['polygon_id'] new_attributes[poly_id][self.target_field] += pop # Update population count for each category cat = new_attributes[poly_id][category_title] categories[cat] += pop # Count totals total = int(numpy.sum(E.get_data(nan=0))) # Don't show digits less than a 1000 if total > 1000: total = total // 1000 * 1000 # Count number and cumulative for each zone cum = 0 pops = {} cums = {} for name in category_names: if category_title == 'Radius': key = name * 1000 # Convert to meters else: key = name pop = int(categories[key]) if pop > 1000: pop = pop // 1000 * 1000 cum += pop if cum > 1000: cum = cum // 1000 * 1000 pops[name] = pop cums[name] = cum # Use final accumulation as total number needing evac evacuated = cum # Calculate estimated needs based on BNPB Perka # 7/2008 minimum bantuan # FIXME (Ole): Refactor into one function to be shared rice = int(evacuated * 2.8) drinking_water = int(evacuated * 17.5) water = int(evacuated * 67) family_kits = int(evacuated / 5) toilets = int(evacuated / 20) # Generate impact report for the pdf map blank_cell = '' table_body = [ question, TableRow( [tr('Volcanos considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([ tr('People needing evacuation'), '%s' % format_int(evacuated), blank_cell ], header=True), TableRow( [category_header, tr('Total'), tr('Cumulative')], header=True) ] for name in category_names: table_body.append( TableRow( [name, format_int(pops[name]), format_int(cums[name])])) table_body.extend([ TableRow( tr('Map shows population affected in ' 'each of volcano hazard polygons.')), TableRow([tr('Needs per week'), tr('Total'), blank_cell], header=True), [tr('Rice [kg]'), format_int(rice), blank_cell], [tr('Drinking Water [l]'), format_int(drinking_water), blank_cell], [tr('Clean Water [l]'), format_int(water), blank_cell], [tr('Family Kits'), format_int(family_kits), blank_cell], [tr('Toilets'), format_int(toilets), blank_cell] ]) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([ TableRow(tr('Notes'), header=True), tr('Total population %s in the viewable area') % format_int(total), tr('People need evacuation if they are within the ' 'volcanic hazard zones.') ]) impact_summary = Table(table_body).toNewlineFreeString() map_title = tr('People affected by volcanic hazard zone') # Define classes for legend for flooded population counts colours = [ '#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000' ] population_counts = [x[self.target_field] for x in new_attributes] cls = [0] + numpy.linspace(1, max(population_counts), len(colours)).tolist() # Define style info for output polygons showing population counts style_classes = [] for i, colour in enumerate(colours): lo = cls[i] hi = cls[i + 1] if i == 0: label = tr('0') else: label = tr('%i - %i') % (lo, hi) entry = dict(label=label, colour=colour, min=lo, max=hi, transparency=50, size=1) style_classes.append(entry) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, legend_title=tr('Population Count')) # Create vector layer and return V = Vector(data=new_attributes, projection=H.get_projection(), geometry=H.get_geometry(as_geometry_objects=True), name=tr('Population affected by volcanic hazard zone'), keywords={ 'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title, 'target_field': self.target_field }, style_info=style_info) return V
def run(self, layers): """Risk plugin for volcano population evacuation :param layers: List of layers expected to contain where two layers should be present. * my_hazard: Vector polygon layer of volcano impact zones * my_exposure: Raster layer of population data on the same grid as my_hazard Counts number of people exposed to volcano event. :returns: Map of population exposed to the volcano hazard zone. The returned dict will include a table with number of people evacuated and supplies required. :rtype: dict """ # Identify hazard and exposure layers my_hazard = get_hazard_layer(layers) # Volcano KRB my_exposure = get_exposure_layer(layers) question = get_question( my_hazard.get_name(), my_exposure.get_name(), self) # Input checks if not my_hazard.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % my_hazard.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. I got %s with ' 'layer type %s' % (my_hazard.get_name(), my_hazard.get_geometry_name())) if not (my_hazard.is_polygon_data or my_hazard.is_point_data): raise Exception(msg) if my_hazard.is_point_data: # Use concentric circles radii = self.parameters['distance [km]'] centers = my_hazard.get_geometry() attributes = my_hazard.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters my_hazard = make_circular_polygon( centers, rad_m, attributes=attributes) category_title = 'Radius' category_header = tr('Distance [km]') category_names = radii name_attribute = 'NAME' # As in e.g. the Smithsonian dataset else: # Use hazard map category_title = 'KRB' category_header = tr('Category') # FIXME (Ole): Change to English and use translation system category_names = ['Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I'] name_attribute = 'GUNUNG' # As in e.g. BNPB hazard map attributes = my_hazard.get_data() # Get names of volcanos considered if name_attribute in my_hazard.get_attribute_names(): D = {} for att in my_hazard.get_data(): # Run through all polygons and get unique names D[att[name_attribute]] = None volcano_names = '' for name in D: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') if not category_title in my_hazard.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (my_hazard.get_name(), category_title)) # noinspection PyExceptionInherit raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data( my_hazard, my_exposure, attribute_name='population') # Initialise attributes of output dataset with all attributes # from input polygon and a population count of zero new_attributes = my_hazard.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count affected population per polygon and total evacuated = 0 for attr in P.get_data(): # Get population at this location pop = float(attr['population']) # Update population count for associated polygon poly_id = attr['polygon_id'] new_attributes[poly_id][self.target_field] += pop # Update population count for each category cat = new_attributes[poly_id][category_title] categories[cat] += pop # Count totals total = int(numpy.sum(my_exposure.get_data(nan=0))) # Don't show digits less than a 1000 total = round_thousand(total) # Count number and cumulative for each zone cum = 0 pops = {} cums = {} for name in category_names: if category_title == 'Radius': key = name * 1000 # Convert to meters else: key = name # prevent key error pop = int(categories.get(key, 0)) pop = round_thousand(pop) cum += pop cum = round_thousand(cum) pops[name] = pop cums[name] = cum # Use final accumulation as total number needing evac evacuated = cum tot_needs = evacuated_population_weekly_needs(evacuated) # Generate impact report for the pdf map blank_cell = '' table_body = [question, TableRow([tr('Volcanos considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([tr('People needing evacuation'), '%s' % format_int(evacuated), blank_cell], header=True), TableRow([category_header, tr('Total'), tr('Cumulative')], header=True)] for name in category_names: table_body.append(TableRow([name, format_int(pops[name]), format_int(cums[name])])) table_body.extend([TableRow(tr('Map shows population affected in ' 'each of volcano hazard polygons.')), TableRow([tr('Needs per week'), tr('Total'), blank_cell], header=True), [tr('Rice [kg]'), format_int(tot_needs['rice']), blank_cell], [tr('Drinking Water [l]'), format_int(tot_needs['drinking_water']), blank_cell], [tr('Clean Water [l]'), format_int(tot_needs['water']), blank_cell], [tr('Family Kits'), format_int(tot_needs['family_kits']), blank_cell], [tr('Toilets'), format_int(tot_needs['toilets']), blank_cell]]) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([TableRow(tr('Notes'), header=True), tr('Total population %s in the exposure layer') % format_int(total), tr('People need evacuation if they are within the ' 'volcanic hazard zones.')]) population_counts = [x[self.target_field] for x in new_attributes] impact_summary = Table(table_body).toNewlineFreeString() # check for zero impact if numpy.nanmax(population_counts) == 0 == numpy.nanmin( population_counts): table_body = [ question, TableRow([tr('People needing evacuation'), '%s' % format_int(evacuated), blank_cell], header=True)] my_message = Table(table_body).toNewlineFreeString() raise ZeroImpactException(my_message) # Create style colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] classes = create_classes(population_counts, len(colours)) interval_classes = humanize_class(classes) # Define style info for output polygons showing population counts style_classes = [] for i in xrange(len(colours)): style_class = dict() style_class['label'] = create_label(interval_classes[i]) if i == 0: transparency = 100 style_class['min'] = 0 else: transparency = 30 style_class['min'] = classes[i - 1] style_class['transparency'] = transparency style_class['colour'] = colours[i] style_class['max'] = classes[i] style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, style_type='graduatedSymbol') # For printing map purpose map_title = tr('People affected by volcanic hazard zone') legend_notes = tr('Thousand separator is represented by %s' % get_thousand_separator()) legend_units = tr('(people)') legend_title = tr('Population count') # Create vector layer and return V = Vector(data=new_attributes, projection=my_hazard.get_projection(), geometry=my_hazard.get_geometry(as_geometry_objects=True), name=tr('Population affected by volcanic hazard zone'), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'target_field': self.target_field, 'map_title': map_title, 'legend_notes': legend_notes, 'legend_units': legend_units, 'legend_title': legend_title}, style_info=style_info) return V
def run(self, layers): """Risk plugin for volcano population evacuation :param layers: List of layers expected to contain where two layers should be present. * my_hazard: Vector polygon layer of volcano impact zones * my_exposure: Raster layer of population data on the same grid as my_hazard Counts number of people exposed to volcano event. :returns: Map of population exposed to the volcano hazard zone. The returned dict will include a table with number of people evacuated and supplies required. :rtype: dict """ # Identify hazard and exposure layers my_hazard = get_hazard_layer(layers) # Volcano KRB my_exposure = get_exposure_layer(layers) question = get_question(my_hazard.get_name(), my_exposure.get_name(), self) # Input checks if not my_hazard.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % my_hazard.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. I got %s with ' 'layer type %s' % (my_hazard.get_name(), my_hazard.get_geometry_name())) if not (my_hazard.is_polygon_data or my_hazard.is_point_data): raise Exception(msg) if my_hazard.is_point_data: # Use concentric circles radii = self.parameters['distance [km]'] centers = my_hazard.get_geometry() attributes = my_hazard.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters my_hazard = make_circular_polygon(centers, rad_m, attributes=attributes) category_title = 'Radius' category_header = tr('Distance [km]') category_names = radii name_attribute = 'NAME' # As in e.g. the Smithsonian dataset else: # Use hazard map category_title = 'KRB' category_header = tr('Category') # FIXME (Ole): Change to English and use translation system category_names = [ 'Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I' ] name_attribute = 'GUNUNG' # As in e.g. BNPB hazard map attributes = my_hazard.get_data() # Get names of volcanos considered if name_attribute in my_hazard.get_attribute_names(): D = {} for att in my_hazard.get_data(): # Run through all polygons and get unique names D[att[name_attribute]] = None volcano_names = '' for name in D: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') if not category_title in my_hazard.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (my_hazard.get_name(), category_title)) # noinspection PyExceptionInherit raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(my_hazard, my_exposure, attribute_name='population') # Initialise attributes of output dataset with all attributes # from input polygon and a population count of zero new_attributes = my_hazard.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count affected population per polygon and total evacuated = 0 for attr in P.get_data(): # Get population at this location pop = float(attr['population']) # Update population count for associated polygon poly_id = attr['polygon_id'] new_attributes[poly_id][self.target_field] += pop # Update population count for each category cat = new_attributes[poly_id][category_title] categories[cat] += pop # Count totals total = int(numpy.sum(my_exposure.get_data(nan=0))) # Don't show digits less than a 1000 total = round_thousand(total) # Count number and cumulative for each zone cum = 0 pops = {} cums = {} for name in category_names: if category_title == 'Radius': key = name * 1000 # Convert to meters else: key = name # prevent key error pop = int(categories.get(key, 0)) pop = round_thousand(pop) cum += pop cum = round_thousand(cum) pops[name] = pop cums[name] = cum # Use final accumulation as total number needing evac evacuated = cum tot_needs = evacuated_population_weekly_needs(evacuated) # Generate impact report for the pdf map blank_cell = '' table_body = [ question, TableRow( [tr('Volcanos considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([ tr('People needing evacuation'), '%s' % format_int(evacuated), blank_cell ], header=True), TableRow( [category_header, tr('Total'), tr('Cumulative')], header=True) ] for name in category_names: table_body.append( TableRow( [name, format_int(pops[name]), format_int(cums[name])])) table_body.extend([ TableRow( tr('Map shows population affected in ' 'each of volcano hazard polygons.')), TableRow([tr('Needs per week'), tr('Total'), blank_cell], header=True), [tr('Rice [kg]'), format_int(tot_needs['rice']), blank_cell], [ tr('Drinking Water [l]'), format_int(tot_needs['drinking_water']), blank_cell ], [ tr('Clean Water [l]'), format_int(tot_needs['water']), blank_cell ], [ tr('Family Kits'), format_int(tot_needs['family_kits']), blank_cell ], [tr('Toilets'), format_int(tot_needs['toilets']), blank_cell] ]) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([ TableRow(tr('Notes'), header=True), tr('Total population %s in the exposure layer') % format_int(total), tr('People need evacuation if they are within the ' 'volcanic hazard zones.') ]) population_counts = [x[self.target_field] for x in new_attributes] impact_summary = Table(table_body).toNewlineFreeString() # check for zero impact if numpy.nanmax(population_counts) == 0 == numpy.nanmin( population_counts): table_body = [ question, TableRow([ tr('People needing evacuation'), '%s' % format_int(evacuated), blank_cell ], header=True) ] my_message = Table(table_body).toNewlineFreeString() raise ZeroImpactException(my_message) # Create style colours = [ '#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000' ] classes = create_classes(population_counts, len(colours)) interval_classes = humanize_class(classes) # Define style info for output polygons showing population counts style_classes = [] for i in xrange(len(colours)): style_class = dict() style_class['label'] = create_label(interval_classes[i]) if i == 0: transparency = 100 style_class['min'] = 0 else: transparency = 30 style_class['min'] = classes[i - 1] style_class['transparency'] = transparency style_class['colour'] = colours[i] style_class['max'] = classes[i] style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, style_type='graduatedSymbol') # For printing map purpose map_title = tr('People affected by volcanic hazard zone') legend_notes = tr('Thousand separator is represented by %s' % get_thousand_separator()) legend_units = tr('(people)') legend_title = tr('Population count') # Create vector layer and return V = Vector(data=new_attributes, projection=my_hazard.get_projection(), geometry=my_hazard.get_geometry(as_geometry_objects=True), name=tr('Population affected by volcanic hazard zone'), keywords={ 'impact_summary': impact_summary, 'impact_table': impact_table, 'target_field': self.target_field, 'map_title': map_title, 'legend_notes': legend_notes, 'legend_units': legend_units, 'legend_title': legend_title }, style_info=style_info) return V
def run(self, layers): """Risk plugin for volcano hazard on building/structure Input layers: List of layers expected to contain my_hazard: Hazard layer of volcano my_exposure: Vector layer of structure data on the same grid as my_hazard Counts number of building exposed to each volcano hazard zones. Return Map of building exposed to volcanic hazard zones Table with number of buildings affected """ # Identify hazard and exposure layers my_hazard = get_hazard_layer(layers) # Volcano hazard layer my_exposure = get_exposure_layer(layers) is_point_data = False question = get_question(my_hazard.get_name(), my_exposure.get_name(), self) # Input checks if not my_hazard.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % my_hazard.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. ' 'I got %s with layer ' 'type %s' % (my_hazard.get_name(), my_hazard.get_geometry_name())) if not (my_hazard.is_polygon_data or my_hazard.is_point_data): raise Exception(msg) if my_hazard.is_point_data: # Use concentric circles radii = self.parameters['distances [km]'] is_point_data = True centers = my_hazard.get_geometry() attributes = my_hazard.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters Z = make_circular_polygon(centers, rad_m, attributes=attributes) # NOTE (Sunni) : I commented out this one because there will be # a permission problem on windows # Z.write_to_file('Marapi_evac_zone_%s.shp' % str(rad_m)) # To check category_title = 'Radius' my_hazard = Z category_names = rad_m name_attribute = 'NAME' # As in e.g. the Smithsonian dataset else: # Use hazard map category_title = 'KRB' # FIXME (Ole): Change to English and use translation system category_names = ['Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I'] name_attribute = 'GUNUNG' # As in e.g. BNPB hazard map # Get names of volcanos considered if name_attribute in my_hazard.get_attribute_names(): D = {} for att in my_hazard.get_data(): # Run through all polygons and get unique names D[att[name_attribute]] = None volcano_names = '' for name in D: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') if not category_title in my_hazard.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (my_hazard.get_name(), category_title)) raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(my_hazard, my_exposure) # Initialise attributes of output dataset with all attributes # from input polygon and a population count of zero new_attributes = my_hazard.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count affected population per polygon and total # total_affected = 0 for attr in P.get_data(): # Update building count for associated polygon poly_id = attr['polygon_id'] if poly_id is not None: new_attributes[poly_id][self.target_field] += 1 # Update building count for each category cat = new_attributes[poly_id][category_title] categories[cat] += 1 # Update total # total_affected += 1 # Count totals total = len(my_exposure) # Generate simple impact report blank_cell = '' table_body = [question, TableRow([tr('Volcanos considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([tr('Distance [km]'), tr('Total'), tr('Cumulative')], header=True)] cum = 0 for name in category_names: # prevent key error count = categories.get(name, 0) cum += count if is_point_data: name = int(name) / 1000 table_body.append(TableRow([name, format_int(count), format_int(cum)])) table_body.append(TableRow(tr('Map shows buildings affected in ' 'each of volcano hazard polygons.'))) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([TableRow(tr('Notes'), header=True), tr('Total number of buildings %s in the viewable ' 'area') % format_int(total), tr('Only buildings available in OpenStreetMap ' 'are considered.')]) impact_summary = Table(table_body).toNewlineFreeString() map_title = tr('Buildings affected by volcanic hazard zone') # Define classes for legend for flooded building counts colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] building_counts = [x[self.target_field] for x in new_attributes] cls = [0] + numpy.linspace(1, max(building_counts), len(colours)).tolist() # Define style info for output polygons showing population counts style_classes = [] for i, colour in enumerate(colours): lo = cls[i] hi = cls[i + 1] if i == 0: label = tr('0') else: label = tr('%i - %i') % (lo, hi) entry = dict(label=label, colour=colour, min=lo, max=hi, transparency=0, size=1) style_classes.append(entry) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, legend_title=tr('Building Count')) # Create vector layer and return V = Vector(data=new_attributes, projection=my_hazard.get_projection(), geometry=my_hazard.get_geometry(as_geometry_objects=True), name=tr('Buildings affected by volcanic hazard zone'), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title, 'target_field': self.target_field}, style_info=style_info) return V
def run(self, layers): """Risk plugin for flood population evacuation Input layers: List of layers expected to contain H: Raster layer of volcano depth P: Raster layer of population data on the same grid as H Counts number of people exposed to each volcano hazard zones. Return Map of population exposed to volcanic hazard zones Table with number of buildings affected """ # Identify hazard and exposure layers H = get_hazard_layer(layers) # Flood inundation E = get_exposure_layer(layers) question = get_question(H.get_name(), E.get_name(), self) # Input checks if not H.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % H.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. ' 'I got %s with layer ' 'type %s' % (H.get_name(), H.get_geometry_name())) if not (H.is_polygon_data or H.is_point_data): raise Exception(msg) if H.is_point_data: # Use concentric circles radii = self.parameters['distances'] centers = H.get_geometry() attributes = H.get_data() Z = make_circular_polygon(centers, radii, attributes=attributes) Z.write_to_file('Marapi_evac_zone_%s.shp' % str(radii)) # To check category_title = 'Radius' H = Z #category_names = ['%s m' % x for x in radii] category_names = radii else: # Use hazard map category_title = 'KRB' # FIXME (Ole): Change to English and use translation system category_names = ['Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I'] if not category_title in H.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (H.get_name(), category_title)) raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(H, E) # Initialise attributes of output dataset with all attributes # from input polygon and a population count of zero new_attributes = H.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count affected population per polygon and total total_affected = 0 for attr in P.get_data(): # Update building count for associated polygon poly_id = attr['polygon_id'] if poly_id is not None: new_attributes[poly_id][self.target_field] += 1 # Update building count for each category cat = new_attributes[poly_id][category_title] categories[cat] += 1 # Update total total_affected += 1 # Count totals total = len(E) # Generate simple impact report table_body = [question, TableRow([tr('Buildings'), tr('Total'), tr('Cumulative')], header=True), TableRow([tr('All'), format_int(total_affected), ''])] cum = 0 for name in category_names: count = categories[name] cum += count table_body.append(TableRow([name, format_int(count), format_int(cum)])) table_body.append(TableRow(tr('Map shows buildings affected in ' 'each of volcano hazard polygons.'))) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([TableRow(tr('Notes'), header=True), tr('Total number of buildings %s in the viewable ' 'area') % format_int(total), tr('Only buildings available in OpenStreetMap ' 'are considered.')]) impact_summary = Table(table_body).toNewlineFreeString() map_title = tr('Buildings affected by volcanic hazard zone') # Define classes for legend for flooded building counts colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] building_counts = [x[self.target_field] for x in new_attributes] cls = [0] + numpy.linspace(1, max(building_counts), len(colours)).tolist() # Define style info for output polygons showing population counts style_classes = [] for i, colour in enumerate(colours): lo = cls[i] hi = cls[i + 1] if i == 0: label = tr('0') else: label = tr('%i - %i') % (lo, hi) entry = dict(label=label, colour=colour, min=lo, max=hi, transparency=0, size=1) style_classes.append(entry) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, legend_title=tr('Building Count')) # Create vector layer and return V = Vector(data=new_attributes, projection=H.get_projection(), geometry=H.get_geometry(as_geometry_objects=True), name=tr('Buildings affected by volcanic hazard zone'), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title, 'target_field': self.target_field}, style_info=style_info) return V
def run(self, layers): """Risk plugin for flood population evacuation Input layers: List of layers expected to contain H: Raster layer of volcano depth P: Raster layer of population data on the same grid as H Counts number of people exposed to flood levels exceeding specified threshold. Return Map of population exposed to volcanic hazard zones Table with number of buildings affected """ # Identify hazard and exposure layers H = get_hazard_layer(layers) # Flood inundation E = get_exposure_layer(layers) question = get_question(H.get_name(), E.get_name(), self) # Input checks if not H.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % H.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. ' 'I got %s with layer ' 'type %s' % (H.get_name(), H.get_geometry_name())) if not (H.is_polygon_data or H.is_point_data): raise Exception(msg) if H.is_point_data: # Use concentric circles radii = self.parameters['distances'] centers = H.get_geometry() attributes = H.get_data() Z = make_circular_polygon(centers, radii, attributes=attributes) Z.write_to_file('Marapi_evac_zone_%s.shp' % str(radii)) # To check category_title = 'Radius' H = Z #category_names = ['%s m' % x for x in radii] category_names = radii else: # Use hazard map category_title = 'KRB' # FIXME (Ole): Change to English and use translation system category_names = ['Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I'] if not category_title in H.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (H.get_name(), category_title)) raise InaSAFEError(msg) # Run interpolation function for polygon2raster P = assign_hazard_values_to_exposure_data(H, E) # Initialise attributes of output dataset with all attributes # from input polygon and a population count of zero new_attributes = H.get_data() categories = {} for attr in new_attributes: attr[self.target_field] = 0 cat = attr[category_title] categories[cat] = 0 # Count affected population per polygon and total total_affected = 0 for attr in P.get_data(): # Update building count for associated polygon poly_id = attr['polygon_id'] if poly_id is not None: new_attributes[poly_id][self.target_field] += 1 # Update building count for each category cat = new_attributes[poly_id][category_title] categories[cat] += 1 # Update total total_affected += 1 # Count totals total = len(E) # Generate simple impact report table_body = [question, TableRow([_('Buildings'), _('Total'), _('Cumulative')], header=True), TableRow([_('All'), str(total_affected), ''])] cum = 0 for name in category_names: count = categories[name] cum += count table_body.append(TableRow([name, str(count), str(cum)])) table_body.append(TableRow(_('Map shows buildings affected in ' 'each of volcano hazard polygons.'))) impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([TableRow(_('Notes'), header=True), _('Total number of buildings %i in the viewable ' 'area') % total, _('Only buildings available in OpenStreetMap ' 'are considered.')]) impact_summary = Table(table_body).toNewlineFreeString() map_title = _('Buildings affected by volcanic hazard zone') # Define classes for legend for flooded building counts colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] building_counts = [x[self.target_field] for x in new_attributes] cls = [0] + numpy.linspace(1, max(building_counts), len(colours)).tolist() # Define style info for output polygons showing population counts style_classes = [] for i, colour in enumerate(colours): lo = cls[i] hi = cls[i + 1] if i == 0: label = _('0') else: label = _('%i - %i') % (lo, hi) entry = dict(label=label, colour=colour, min=lo, max=hi, transparency=0, size=1) style_classes.append(entry) # Override style info with new classes and name style_info = dict(target_field=self.target_field, style_classes=style_classes, legend_title=_('Building Count')) # Create vector layer and return V = Vector(data=new_attributes, projection=H.get_projection(), geometry=H.get_geometry(as_geometry_objects=True), name=_('Buildings affected by volcanic hazard zone'), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title, 'target_field': self.target_field}, style_info=style_info) return V