def run(self, layers=None): """Counts number of building exposed to each volcano hazard zones. :param layers: List of layers expected to contain. * hazard_layer: Hazard layer of volcano * exposure_layer: Vector layer of structure data on the same grid as hazard_layer :returns: Map of building exposed to volcanic hazard zones. Table with number of buildings affected :rtype: dict """ self.validate() self.prepare(layers) # Target Field target_field = 'zone' # Hazard Zone Attribute hazard_zone_attribute = 'radius' # Not Affected Value not_affected_value = 'Not Affected' # Parameters radii = self.parameters['distances [km]'] volcano_name_attribute = self.parameters['volcano name attribute'] # Identify hazard and exposure layers hazard_layer = self.hazard # Volcano hazard layer exposure_layer = self.exposure # Building exposure layer # Input checks if not hazard_layer.is_point_data: message = ( 'Input hazard must be a vector point layer. I got %s ' 'with layer type %s' % ( hazard_layer.get_name(), hazard_layer.get_geometry_name())) raise Exception(message) # Make hazard layer by buffering the point centers = hazard_layer.get_geometry() features = hazard_layer.get_data() radii_meter = [x * 1000 for x in radii] # Convert to meters hazard_layer = buffer_points( centers, radii_meter, hazard_zone_attribute, data_table=features) # Category names for the impact zone category_names = radii_meter category_names.append(not_affected_value) # Get names of volcanoes considered if volcano_name_attribute in hazard_layer.get_attribute_names(): volcano_name_list = set() for row in hazard_layer.get_data(): # Run through all polygons and get unique names volcano_name_list.add(row[volcano_name_attribute]) self.volcano_names = ', '.join(volcano_name_list) # Find the target field name that has no conflict with the attribute # names in the hazard layer hazard_attribute_names = hazard_layer.get_attribute_names() target_field = get_non_conflicting_attribute_name( target_field, hazard_attribute_names) # Run interpolation function for polygon2polygon interpolated_layer = assign_hazard_values_to_exposure_data( hazard_layer, exposure_layer, attribute_name=None) # Extract relevant interpolated layer data attribute_names = interpolated_layer.get_attribute_names() features = interpolated_layer.get_data() self.buildings = {} self.affected_buildings = OrderedDict() for category in radii_meter: self.affected_buildings[category] = {} # Iterate the interpolated building layer for i in range(len(features)): hazard_value = features[i][hazard_zone_attribute] if not hazard_value: hazard_value = not_affected_value features[i][target_field] = hazard_value # Count affected buildings by usage type if available usage = get_osm_building_usage(attribute_names, features[i]) if usage is [None, 'NULL', 'null', 'Null', 0]: usage = tr('Unknown') if usage not in self.buildings: self.buildings[usage] = 0 for category in self.affected_buildings.keys(): self.affected_buildings[category][ usage] = OrderedDict([ (tr('Buildings Affected'), 0)]) self.buildings[usage] += 1 if hazard_value in self.affected_buildings.keys(): self.affected_buildings[hazard_value][usage][ tr('Buildings Affected')] += 1 # Lump small entries and 'unknown' into 'other' category self._consolidate_to_other() # Generate simple impact report impact_summary = impact_table = self.generate_html_report() # Create style colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] colours = colours[::-1] # flip colours = colours[:len(category_names)] style_classes = [] i = 0 for category_name in category_names: style_class = dict() style_class['label'] = tr(category_name) style_class['transparency'] = 0 style_class['value'] = category_name style_class['size'] = 1 if i >= len(category_names): i = len(category_names) - 1 style_class['colour'] = colours[i] i += 1 style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=target_field, style_classes=style_classes, style_type='categorizedSymbol') # For printing map purpose map_title = tr('Buildings affected by volcanic buffered point') 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 impact_layer = Vector( data=features, projection=interpolated_layer.get_projection(), geometry=interpolated_layer.get_geometry(), name=tr('Buildings affected by volcanic buffered point'), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'target_field': target_field, 'map_title': map_title, 'legend_notes': legend_notes, 'legend_units': legend_units, 'legend_title': legend_title}, style_info=style_info) self._impact = impact_layer return impact_layer
def run(self, layers): """Risk plugin for volcano population evacuation. :param layers: List of layers expected to contain where two layers should be present. * hazard_layer: Vector polygon layer of volcano impact zones * exposure_layer: Raster layer of population data on the same grid as hazard_layer 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 :raises: * Exception - When hazard layer is not vector layer * RadiiException - When radii are not valid (they need to be monotonically increasing) """ # Identify hazard and exposure layers hazard_layer = get_hazard_layer(layers) # Volcano KRB exposure_layer = get_exposure_layer(layers) question = get_question( hazard_layer.get_name(), exposure_layer.get_name(), self) # Input checks if not hazard_layer.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % hazard_layer.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. I got %s with ' 'layer type %s' % (hazard_layer.get_name(), hazard_layer.get_geometry_name())) if not (hazard_layer.is_polygon_data or hazard_layer.is_point_data): raise Exception(msg) data_table = hazard_layer.get_data() if hazard_layer.is_point_data: # Use concentric circles radii = self.parameters['distance [km]'] centers = hazard_layer.get_geometry() rad_m = [x * 1000 for x in radii] # Convert to meters hazard_layer = buffer_points(centers, rad_m, data_table=data_table) 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 # Get names of volcanoes considered if name_attribute in hazard_layer.get_attribute_names(): volcano_name_list = [] # Run through all polygons and get unique names for row in data_table: volcano_name_list.append(row[name_attribute]) volcano_names = '' for name in volcano_name_list: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') # Check if category_title exists in hazard_layer if not category_title in hazard_layer.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (hazard_layer.get_name(), category_title)) # noinspection PyExceptionInherit raise InaSAFEError(msg) # Find the target field name that has no conflict with default target attribute_names = hazard_layer.get_attribute_names() new_target_field = get_non_conflicting_attribute_name( self.target_field, attribute_names) self.target_field = new_target_field # Run interpolation function for polygon2raster interpolated_layer = assign_hazard_values_to_exposure_data( hazard_layer, exposure_layer, attribute_name=self.target_field) # Initialise data_table of output dataset with all data_table # from input polygon and a population count of zero new_data_table = hazard_layer.get_data() categories = {} for row in new_data_table: row[self.target_field] = 0 category = row[category_title] categories[category] = 0 # Count affected population per polygon and total for row in interpolated_layer.get_data(): # Get population at this location population = float(row[self.target_field]) # Update population count for associated polygon poly_id = row['polygon_id'] new_data_table[poly_id][self.target_field] += population # Update population count for each category category = new_data_table[poly_id][category_title] categories[category] += population # Count totals total = int(numpy.sum(exposure_layer.get_data(nan=0))) # Don't show digits less than a 1000 total = round_thousand(total) # Count number and cumulative for each zone cumulative = 0 all_categories_population = {} all_categories_cumulative = {} for name in category_names: if category_title == 'Radius': key = name * 1000 # Convert to meters else: key = name # prevent key error population = int(categories.get(key, 0)) population = round_thousand(population) cumulative += population cumulative = round_thousand(cumulative) all_categories_population[name] = population all_categories_cumulative[name] = cumulative # Use final accumulation as total number needing evacuation evacuated = cumulative # Calculate estimated minimum needs minimum_needs = self.parameters['minimum needs'] total_needs = evacuated_population_weekly_needs( evacuated, minimum_needs) # Generate impact report for the pdf map blank_cell = '' table_body = [question, TableRow([tr('Volcanoes 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(all_categories_population[name]), format_int(all_categories_cumulative[name])])) table_body.extend([ TableRow(tr( 'Map shows the number of people affected in each of volcano ' 'hazard polygons.')), TableRow( [tr('Needs per week'), tr('Total'), blank_cell], header=True), [tr('Rice [kg]'), format_int(total_needs['rice']), blank_cell], [ tr('Drinking Water [l]'), format_int(total_needs['drinking_water']), blank_cell], [tr('Clean Water [l]'), format_int(total_needs['water']), blank_cell], [tr('Family Kits'), format_int(total_needs['family_kits']), blank_cell], [tr('Toilets'), format_int(total_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_data_table] 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 impact_layer = Vector( data=new_data_table, projection=hazard_layer.get_projection(), geometry=hazard_layer.get_geometry(as_geometry_objects=True), name=tr('People 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 impact_layer
def run(self, layers): """Risk plugin for volcano hazard on building/structure. Counts number of building exposed to each volcano hazard zones. :param layers: List of layers expected to contain. * hazard_layer: Hazard layer of volcano * exposure_layer: Vector layer of structure data on the same grid as hazard_layer :returns: Map of building exposed to volcanic hazard zones. Table with number of buildings affected :rtype: dict """ # Identify hazard and exposure layers hazard_layer = get_hazard_layer(layers) # Volcano hazard layer exposure_layer = get_exposure_layer(layers) is_point_data = False question = get_question( hazard_layer.get_name(), exposure_layer.get_name(), self) # Input checks if not hazard_layer.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % hazard_layer.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. I got %s ' 'with layer type %s' % (hazard_layer.get_name(), hazard_layer.get_geometry_name())) if not (hazard_layer.is_polygon_data or hazard_layer.is_point_data): raise Exception(msg) if hazard_layer.is_point_data: # Use concentric circles radii = self.parameters['distances [km]'] is_point_data = True centers = hazard_layer.get_geometry() attributes = hazard_layer.get_data() rad_m = [x * 1000 for x in radii] # Convert to meters hazard_layer = buffer_points(centers, rad_m, data_table=attributes) # To check category_title = 'Radius' 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 volcanoes considered if name_attribute in hazard_layer.get_attribute_names(): volcano_name_list = [] for row in hazard_layer.get_data(): # Run through all polygons and get unique names volcano_name_list.append(row[name_attribute]) volcano_names = '' for name in volcano_name_list: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') # Check if category_title exists in hazard_layer if not category_title in hazard_layer.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (hazard_layer.get_name(), category_title)) # noinspection PyExceptionInherit raise InaSAFEError(msg) # Find the target field name that has no conflict with default # target attribute_names = hazard_layer.get_attribute_names() new_target_field = get_non_conflicting_attribute_name( self.target_field, attribute_names) self.target_field = new_target_field # Run interpolation function for polygon2raster interpolated_layer = assign_hazard_values_to_exposure_data( hazard_layer, exposure_layer) # Initialise attributes of output dataset with all attributes # from input polygon and a building count of zero new_data_table = hazard_layer.get_data() categories = {} for row in new_data_table: row[self.target_field] = 0 category = row[category_title] categories[category] = 0 # Count impacted building per polygon and total for row in interpolated_layer.get_data(): # Update building count for associated polygon poly_id = row['polygon_id'] if poly_id is not None: new_data_table[poly_id][self.target_field] += 1 # Update building count for each category category = new_data_table[poly_id][category_title] categories[category] += 1 # Count totals total = len(exposure_layer) # Generate simple impact report blank_cell = '' table_body = [question, TableRow([tr('Volcanoes considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([tr('Distance [km]'), tr('Total'), tr('Cumulative')], header=True)] cumulative = 0 for name in category_names: # prevent key error count = categories.get(name, 0) cumulative += count if is_point_data: name = int(name) / 1000 table_body.append(TableRow([name, format_int(count), format_int(cumulative)])) 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_data_table] if max(building_counts) == 0 == min(building_counts): table_body = [ question, TableRow([tr('Number of buildings affected'), '%s' % format_int(cumulative), 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'] # Create Classes classes = create_classes(building_counts, len(colours)) # Create Interval Classes 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: style_class['min'] = 0 else: style_class['min'] = classes[i - 1] style_class['transparency'] = 30 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 impact_layer = Vector( data=new_data_table, projection=hazard_layer.get_projection(), geometry=hazard_layer.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 impact_layer
def run(self, layers=None): """Counts number of building exposed to each volcano hazard zones. :param layers: List of layers expected to contain. * hazard_layer: Hazard layer of volcano * exposure_layer: Vector layer of structure data on the same grid as hazard_layer :returns: Map of building exposed to volcanic hazard zones. Table with number of buildings affected :rtype: dict """ self.validate() self.prepare(layers) # Target Field target_field = 'zone' # Hazard Zone Attribute hazard_zone_attribute = 'radius' # Not Affected Value not_affected_value = 'Not Affected' # Parameters radii = self.parameters['distances [km]'] volcano_name_attribute = self.parameters['volcano name attribute'] # Identify hazard and exposure layers hazard_layer = self.hazard # Volcano hazard layer exposure_layer = self.exposure # Building exposure layer # Input checks if not hazard_layer.is_point_data: message = ( 'Input hazard must be a vector point layer. I got %s ' 'with layer type %s' % (hazard_layer.get_name(), hazard_layer.get_geometry_name())) raise Exception(message) # Make hazard layer by buffering the point centers = hazard_layer.get_geometry() features = hazard_layer.get_data() radii_meter = [x * 1000 for x in radii] # Convert to meters hazard_layer = buffer_points(centers, radii_meter, hazard_zone_attribute, data_table=features) # Category names for the impact zone category_names = radii_meter category_names.append(not_affected_value) # Get names of volcanoes considered if volcano_name_attribute in hazard_layer.get_attribute_names(): volcano_name_list = set() for row in hazard_layer.get_data(): # Run through all polygons and get unique names volcano_name_list.add(row[volcano_name_attribute]) self.volcano_names = ', '.join(volcano_name_list) else: self.volcano_names = tr('Not specified in data') # Find the target field name that has no conflict with the attribute # names in the hazard layer hazard_attribute_names = hazard_layer.get_attribute_names() target_field = get_non_conflicting_attribute_name( target_field, hazard_attribute_names) # Run interpolation function for polygon2polygon interpolated_layer = assign_hazard_values_to_exposure_data( hazard_layer, exposure_layer, attribute_name=None) # Extract relevant interpolated layer data attribute_names = interpolated_layer.get_attribute_names() features = interpolated_layer.get_data() self.buildings = {} self.affected_buildings = OrderedDict() for category in radii_meter: self.affected_buildings[category] = {} # Iterate the interpolated building layer for i in range(len(features)): hazard_value = features[i][hazard_zone_attribute] if not hazard_value: hazard_value = not_affected_value features[i][target_field] = hazard_value # Count affected buildings by usage type if available usage = get_osm_building_usage(attribute_names, features[i]) if usage is [None, 'NULL', 'null', 'Null', 0]: usage = tr('Unknown') if usage not in self.buildings: self.buildings[usage] = 0 for category in self.affected_buildings.keys(): self.affected_buildings[category][usage] = OrderedDict([ (tr('Buildings Affected'), 0) ]) self.buildings[usage] += 1 if hazard_value in self.affected_buildings.keys(): self.affected_buildings[hazard_value][usage][tr( 'Buildings Affected')] += 1 # Lump small entries and 'unknown' into 'other' category self._consolidate_to_other() # Generate simple impact report impact_summary = impact_table = self.generate_html_report() # Create style colours = [ '#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000' ] colours = colours[::-1] # flip colours = colours[:len(category_names)] style_classes = [] i = 0 for category_name in category_names: style_class = dict() style_class['label'] = tr(category_name) style_class['transparency'] = 0 style_class['value'] = category_name style_class['size'] = 1 if i >= len(category_names): i = len(category_names) - 1 style_class['colour'] = colours[i] i += 1 style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=target_field, style_classes=style_classes, style_type='categorizedSymbol') # For printing map purpose map_title = tr('Buildings affected by volcanic buffered point') 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 impact_layer = Vector( data=features, projection=interpolated_layer.get_projection(), geometry=interpolated_layer.get_geometry(), name=tr('Buildings affected by volcanic buffered point'), keywords={ 'impact_summary': impact_summary, 'impact_table': impact_table, 'target_field': target_field, 'map_title': map_title, 'legend_notes': legend_notes, 'legend_units': legend_units, 'legend_title': legend_title }, style_info=style_info) self._impact = impact_layer return impact_layer
def run(self, layers): """Risk plugin for volcano hazard on building/structure. Counts number of building exposed to each volcano hazard zones. :param layers: List of layers expected to contain. * hazard_layer: Hazard layer of volcano * exposure_layer: Vector layer of structure data on the same grid as hazard_layer :returns: Map of building exposed to volcanic hazard zones. Table with number of buildings affected :rtype: dict """ # Parameters not_affected_value = self.parameters['Not affected value'] radii = self.parameters['distances [km]'] target_field = self.parameters['target field'] name_attribute = self.parameters['name attribute'] hazard_zone_attribute = self.parameters['hazard zone attribute'] # Identify hazard and exposure layers hazard_layer = get_hazard_layer(layers) # Volcano hazard layer exposure_layer = get_exposure_layer(layers) # Building exposure layer # Get question question = get_question( hazard_layer.get_name(), exposure_layer.get_name(), self) # Input checks if not hazard_layer.is_vector: message = ('Input hazard %s was not a vector layer as expected ' % hazard_layer.get_name()) raise Exception(message) if not (hazard_layer.is_polygon_data or hazard_layer.is_point_data): message = ( 'Input hazard must be a polygon or point layer. I got %s with ' 'layer type %s' % (hazard_layer.get_name(), hazard_layer.get_geometry_name())) raise Exception(message) if hazard_layer.is_point_data: # Use concentric circles centers = hazard_layer.get_geometry() attributes = hazard_layer.get_data() radii_meter = [x * 1000 for x in radii] # Convert to meters hazard_layer = buffer_points( centers, radii_meter, hazard_zone_attribute, data_table=attributes) # To check category_names = radii_meter else: # FIXME (Ole): Change to English and use translation system # FIXME (Ismail) : Or simply use the values from the hazard layer category_names = ['Kawasan Rawan Bencana III', 'Kawasan Rawan Bencana II', 'Kawasan Rawan Bencana I'] category_names.append(not_affected_value) # Get names of volcanoes considered if name_attribute in hazard_layer.get_attribute_names(): volcano_name_list = set() for row in hazard_layer.get_data(): # Run through all polygons and get unique names volcano_name_list.add(row[name_attribute]) volcano_names = ', '.join(volcano_name_list) else: volcano_names = tr('Not specified in data') # Check if category_title exists in hazard_layer if hazard_zone_attribute not in hazard_layer.get_attribute_names(): message = ( 'Hazard data %s did not contain expected attribute %s ' % (hazard_layer.get_name(), hazard_zone_attribute)) # noinspection PyExceptionInherit raise InaSAFEError(message) # Find the target field name that has no conflict with default # target attribute_names = hazard_layer.get_attribute_names() target_field = get_non_conflicting_attribute_name( target_field, attribute_names) # Run interpolation function for polygon2raster interpolated_layer = assign_hazard_values_to_exposure_data( hazard_layer, exposure_layer, attribute_name=None) # Extract relevant exposure data attribute_names = interpolated_layer.get_attribute_names() attribute_names_lower = [ attribute_name.lower() for attribute_name in attribute_names] attributes = interpolated_layer.get_data() interpolate_size = len(interpolated_layer) building_per_category = {} building_usages = [] other_sum = {} for category_name in category_names: building_per_category[category_name] = {} building_per_category[category_name]['total'] = 0 other_sum[category_name] = 0 # Building attribute that should be looked up to get the usage building_type_attributes = [ 'type', 'amenity', 'building_t', 'office', 'tourism', 'leisure', 'use', ] for i in range(interpolate_size): hazard_value = attributes[i][hazard_zone_attribute] if not hazard_value: hazard_value = not_affected_value attributes[i][target_field] = hazard_value if hazard_value in building_per_category.keys(): building_per_category[hazard_value]['total'] += 1 elif not hazard_value: building_per_category[not_affected_value]['total'] += 1 else: building_per_category[hazard_value] = {} building_per_category[hazard_value]['total'] = 1 # Count affected buildings by usage type if available usage = None for building_type_attribute in building_type_attributes: if ( building_type_attribute in attribute_names_lower and ( usage is None or usage == 0)): attribute_index = attribute_names_lower.index( building_type_attribute) field_name = attribute_names[attribute_index] usage = attributes[i][field_name] if ( 'building' in attribute_names_lower and ( usage is None or usage == 0)): attribute_index = attribute_names_lower.index('building') field_name = attribute_names[attribute_index] usage = attributes[i][field_name] if usage == 'yes': usage = 'building' if usage is None or usage == 0: usage = tr('unknown') if usage not in building_usages: building_usages.append(usage) for building in building_per_category.values(): building[usage] = 0 building_per_category[hazard_value][usage] += 1 # Generate simple impact report blank_cell = '' table_body = [question, TableRow([tr('Volcanoes considered'), '%s' % volcano_names, blank_cell], header=True)] table_headers = [tr('Building type')] table_headers += [tr(x) for x in category_names] table_headers += [tr('Total')] table_body += [TableRow(table_headers, header=True)] for building_usage in building_usages: building_usage_good = building_usage.replace('_', ' ') building_usage_good = building_usage_good.capitalize() building_sum = sum([ building_per_category[category_name][building_usage] for category_name in category_names ]) # Filter building type that has no less than 25 items if building_sum >= 25: row = [tr(building_usage_good)] building_sum = 0 for category_name in category_names: building_sub_sum = building_per_category[category_name][ building_usage] row.append(format_int(building_sub_sum)) building_sum += building_sub_sum row.append(format_int(building_sum)) table_body.append(row) else: for category_name in category_names: if category_name in other_sum.keys(): other_sum[category_name] += building_per_category[ category_name][building_usage] else: other_sum[category_name] = building_per_category[ category_name][building_usage] # Adding others building type to the report. other_row = [tr('Other')] other_building_total = 0 for category_name in category_names: other_building_sum = other_sum[category_name] other_row.append(format_int(other_building_sum)) other_building_total += other_building_sum other_row.append(format_int(other_building_total)) table_body.append(other_row) all_row = [tr('Total')] all_row += [format_int(building_per_category[category_name]['total']) for category_name in category_names] total = sum([building_per_category[category_name]['total'] for category_name in category_names]) all_row += [format_int(total)] table_body.append(TableRow(all_row, header=True)) table_body += [TableRow(tr('Map shows buildings affected in each of ' 'volcano hazard polygons.'))] impact_table = Table(table_body).toNewlineFreeString() impact_summary = impact_table # 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.')]) # Create style colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] colours = colours[::-1] # flip colours = colours[:len(category_names)] style_classes = [] i = 0 for category_name in category_names: style_class = dict() style_class['label'] = tr(category_name) style_class['transparency'] = 0 style_class['value'] = category_name style_class['size'] = 1 if i >= len(category_names): i = len(category_names) - 1 style_class['colour'] = colours[i] i += 1 style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=target_field, style_classes=style_classes, style_type='categorizedSymbol') # 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 impact_layer = Vector( data=attributes, projection=interpolated_layer.get_projection(), geometry=interpolated_layer.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': target_field, 'map_title': map_title, 'legend_notes': legend_notes, 'legend_units': legend_units, 'legend_title': legend_title}, style_info=style_info) return impact_layer
from safe.engine.utilities import buffer_points 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 = buffer_points(center, radius, 'Radius') Z.write_to_file('Marapi_evac_zone_%im.shp' % radius)
def run(self, layers=None): """Run volcano point population evacuation Impact Function. :param layers: List of layers expected to contain where two layers should be present. * hazard_layer: Vector point layer. * exposure_layer: Raster layer of population data on the same grid as hazard_layer 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 :raises: * Exception - When hazard layer is not vector layer * RadiiException - When radii are not valid (they need to be monotonically increasing) """ self.validate() self.prepare(layers) # Parameters radii = self.parameters['distance [km]'] name_attribute = self.parameters['volcano name attribute'] # Identify hazard and exposure layers hazard_layer = self.hazard exposure_layer = self.exposure # Input checks if not hazard_layer.is_point_data: msg = ( 'Input hazard must be a polygon or point layer. I got %s with ' 'layer type %s' % (hazard_layer.get_name(), hazard_layer.get_geometry_name())) raise Exception(msg) data_table = hazard_layer.get_data() # Use concentric circles category_title = 'Radius' category_header = tr('Distance [km]') centers = hazard_layer.get_geometry() rad_m = [x * 1000 for x in radii] # Convert to meters hazard_layer = buffer_points( centers, rad_m, category_title, data_table=data_table) # Get names of volcanoes considered if name_attribute in hazard_layer.get_attribute_names(): volcano_name_list = [] # Run through all polygons and get unique names for row in data_table: volcano_name_list.append(row[name_attribute]) volcano_names = '' for radius in volcano_name_list: volcano_names += '%s, ' % radius volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') # Find the target field name that has no conflict with default target attribute_names = hazard_layer.get_attribute_names() new_target_field = get_non_conflicting_attribute_name( self.target_field, attribute_names) self.target_field = new_target_field # Run interpolation function for polygon2raster interpolated_layer, covered_exposure_layer = \ assign_hazard_values_to_exposure_data( hazard_layer, exposure_layer, attribute_name=self.target_field ) # Initialise affected population per categories affected_population = {} for radius in rad_m: affected_population[radius] = 0 nan_warning = False if has_no_data(exposure_layer.get_data(nan=True)): nan_warning = True # Count affected population per polygon and total for row in interpolated_layer.get_data(): # Get population at this location population = row[self.target_field] if not numpy.isnan(population): population = float(population) # Update population count for this category category = row[category_title] affected_population[category] += population # Count totals total_population = population_rounding( int(numpy.nansum(exposure_layer.get_data()))) # Count cumulative for each zone total_affected_population = 0 cumulative_affected_population = {} for radius in rad_m: population = int(affected_population.get(radius, 0)) total_affected_population += population cumulative_affected_population[radius] = total_affected_population minimum_needs = [ parameter.serialize() for parameter in self.parameters['minimum needs'] ] # Generate impact report for the pdf map blank_cell = '' table_body = [ self.question, TableRow( [tr('Volcanoes considered'), '%s' % volcano_names, blank_cell], header=True), TableRow( [tr('People needing evacuation'), '%s' % format_int( population_rounding(total_affected_population)), blank_cell], header=True), TableRow( [category_header, tr('Total'), tr('Cumulative')], header=True)] for radius in rad_m: table_body.append( TableRow( [radius, format_int( population_rounding( affected_population[radius])), format_int( population_rounding( cumulative_affected_population[radius]))])) table_body.extend([ TableRow(tr( 'Map shows the number of people affected in each of volcano ' 'hazard polygons.'))]) total_needs = evacuated_population_needs( total_affected_population, minimum_needs) for frequency, needs in total_needs.items(): table_body.append(TableRow( [ tr('Needs should be provided %s' % frequency), tr('Total') ], header=True)) for resource in needs: table_body.append(TableRow([ tr(resource['table name']), format_int(resource['amount'])])) 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_population), tr('People need evacuation if they are within the ' 'volcanic hazard zones.')]) if nan_warning: table_body.extend([ tr('The population layer contained `no data`. This missing ' 'data was carried through to the impact layer.'), tr('`No data` values in the impact layer were treated as 0 ' 'when counting the affected or total population.') ]) impact_summary = Table(table_body).toNewlineFreeString() # check for zero impact if total_affected_population == 0: table_body = [ self.question, TableRow( [tr('People needing evacuation'), '%s' % format_int(total_affected_population), blank_cell], header=True)] message = Table(table_body).toNewlineFreeString() raise ZeroImpactException(message) # Create style colours = ['#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000'] classes = create_classes( covered_exposure_layer.get_data().flat[:], 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 == 1: label = create_label( interval_classes[i], tr('Low Population [%i people/cell]' % classes[i])) elif i == 4: label = create_label( interval_classes[i], tr('Medium Population [%i people/cell]' % classes[i])) elif i == 7: label = create_label( interval_classes[i], tr('High Population [%i people/cell]' % classes[i])) else: label = create_label(interval_classes[i]) if i == 0: transparency = 100 else: transparency = 0 style_class['label'] = label style_class['quantity'] = classes[i] style_class['colour'] = colours[i] style_class['transparency'] = transparency style_classes.append(style_class) # Override style info with new classes and name style_info = dict( target_field=None, style_classes=style_classes, style_type='rasterStyle') # For printing map purpose map_title = tr('People affected by the buffered point volcano') legend_notes = tr('Thousand separator is represented by %s' % get_thousand_separator()) legend_units = tr('(people per cell)') legend_title = tr('Population') # Create vector layer and return impact_layer = Raster( data=covered_exposure_layer.get_data(), projection=covered_exposure_layer.get_projection(), geotransform=covered_exposure_layer.get_geotransform(), name=tr('People affected by the buffered point volcano'), 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, 'total_needs': total_needs}, style_info=style_info) self._impact = impact_layer return impact_layer
def run(self, layers=None): """Run volcano point population evacuation Impact Function. :param layers: List of layers expected to contain where two layers should be present. * hazard_layer: Vector point layer. * exposure_layer: Raster layer of population data on the same grid as hazard_layer 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 :raises: * Exception - When hazard layer is not vector layer * RadiiException - When radii are not valid (they need to be monotonically increasing) """ self.validate() self.prepare(layers) # Parameters radii = self.parameters['distance [km]'] name_attribute = self.parameters['volcano name attribute'] # Identify hazard and exposure layers hazard_layer = self.hazard exposure_layer = self.exposure # Input checks if not hazard_layer.is_point_data: msg = ( 'Input hazard must be a polygon or point layer. I got %s with ' 'layer type %s' % (hazard_layer.get_name(), hazard_layer.get_geometry_name())) raise Exception(msg) data_table = hazard_layer.get_data() # Use concentric circles category_title = 'Radius' category_header = tr('Distance [km]') centers = hazard_layer.get_geometry() rad_m = [x * 1000 for x in radii] # Convert to meters hazard_layer = buffer_points(centers, rad_m, category_title, data_table=data_table) # Get names of volcanoes considered if name_attribute in hazard_layer.get_attribute_names(): volcano_name_list = [] # Run through all polygons and get unique names for row in data_table: volcano_name_list.append(row[name_attribute]) volcano_names = '' for radius in volcano_name_list: volcano_names += '%s, ' % radius volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') # Find the target field name that has no conflict with default target attribute_names = hazard_layer.get_attribute_names() new_target_field = get_non_conflicting_attribute_name( self.target_field, attribute_names) self.target_field = new_target_field # Run interpolation function for polygon2raster interpolated_layer, covered_exposure_layer = \ assign_hazard_values_to_exposure_data( hazard_layer, exposure_layer, attribute_name=self.target_field ) # Initialise affected population per categories affected_population = {} for radius in rad_m: affected_population[radius] = 0 nan_warning = False if has_no_data(exposure_layer.get_data(nan=True)): nan_warning = True # Count affected population per polygon and total for row in interpolated_layer.get_data(): # Get population at this location population = row[self.target_field] if not numpy.isnan(population): population = float(population) # Update population count for this category category = row[category_title] affected_population[category] += population # Count totals total_population = population_rounding( int(numpy.nansum(exposure_layer.get_data()))) # Count cumulative for each zone total_affected_population = 0 cumulative_affected_population = {} for radius in rad_m: population = int(affected_population.get(radius, 0)) total_affected_population += population cumulative_affected_population[radius] = total_affected_population minimum_needs = [ parameter.serialize() for parameter in self.parameters['minimum needs'] ] # Generate impact report for the pdf map blank_cell = '' table_body = [ self.question, TableRow( [tr('Volcanoes considered'), '%s' % volcano_names, blank_cell], header=True), TableRow([ tr('People needing evacuation'), '%s' % format_int(population_rounding(total_affected_population)), blank_cell ], header=True), TableRow( [category_header, tr('Total'), tr('Cumulative')], header=True) ] for radius in rad_m: table_body.append( TableRow([ radius, format_int(population_rounding( affected_population[radius])), format_int( population_rounding( cumulative_affected_population[radius])) ])) table_body.extend([ TableRow( tr('Map shows the number of people affected in each of volcano ' 'hazard polygons.')) ]) total_needs = evacuated_population_needs(total_affected_population, minimum_needs) for frequency, needs in total_needs.items(): table_body.append( TableRow([ tr('Needs should be provided %s' % frequency), tr('Total') ], header=True)) for resource in needs: table_body.append( TableRow([ tr(resource['table name']), format_int(resource['amount']) ])) 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_population), tr('People need evacuation if they are within the ' 'volcanic hazard zones.') ]) if nan_warning: table_body.extend([ tr('The population layer contained `no data`. This missing ' 'data was carried through to the impact layer.'), tr('`No data` values in the impact layer were treated as 0 ' 'when counting the affected or total population.') ]) impact_summary = Table(table_body).toNewlineFreeString() # check for zero impact if total_affected_population == 0: table_body = [ self.question, TableRow([ tr('People needing evacuation'), '%s' % format_int(total_affected_population), blank_cell ], header=True) ] message = Table(table_body).toNewlineFreeString() raise ZeroImpactException(message) # Create style colours = [ '#FFFFFF', '#38A800', '#79C900', '#CEED00', '#FFCC00', '#FF6600', '#FF0000', '#7A0000' ] classes = create_classes(covered_exposure_layer.get_data().flat[:], 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 == 1: label = create_label( interval_classes[i], tr('Low Population [%i people/cell]' % classes[i])) elif i == 4: label = create_label( interval_classes[i], tr('Medium Population [%i people/cell]' % classes[i])) elif i == 7: label = create_label( interval_classes[i], tr('High Population [%i people/cell]' % classes[i])) else: label = create_label(interval_classes[i]) if i == 0: transparency = 100 else: transparency = 0 style_class['label'] = label style_class['quantity'] = classes[i] style_class['colour'] = colours[i] style_class['transparency'] = transparency style_classes.append(style_class) # Override style info with new classes and name style_info = dict(target_field=None, style_classes=style_classes, style_type='rasterStyle') # For printing map purpose map_title = tr('People affected by the buffered point volcano') legend_notes = tr('Thousand separator is represented by %s' % get_thousand_separator()) legend_units = tr('(people per cell)') legend_title = tr('Population') # Create vector layer and return impact_layer = Raster( data=covered_exposure_layer.get_data(), projection=covered_exposure_layer.get_projection(), geotransform=covered_exposure_layer.get_geotransform(), name=tr('People affected by the buffered point volcano'), 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, 'total_needs': total_needs }, style_info=style_info) self._impact = impact_layer return impact_layer
def run(self, layers): """Risk plugin for volcano population evacuation. :param layers: List of layers expected to contain where two layers should be present. * hazard_layer: Vector polygon layer of volcano impact zones * exposure_layer: Raster layer of population data on the same grid as hazard_layer 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 :raises: * Exception - When hazard layer is not vector layer * RadiiException - When radii are not valid (they need to be monotonically increasing) """ # Identify hazard and exposure layers hazard_layer = get_hazard_layer(layers) # Volcano KRB exposure_layer = get_exposure_layer(layers) question = get_question( hazard_layer.get_name(), exposure_layer.get_name(), self) # Input checks if not hazard_layer.is_vector: msg = ('Input hazard %s was not a vector layer as expected ' % hazard_layer.get_name()) raise Exception(msg) msg = ('Input hazard must be a polygon or point layer. I got %s with ' 'layer type %s' % (hazard_layer.get_name(), hazard_layer.get_geometry_name())) if not (hazard_layer.is_polygon_data or hazard_layer.is_point_data): raise Exception(msg) data_table = hazard_layer.get_data() if hazard_layer.is_point_data: # Use concentric circles radii = self.parameters['distance [km]'] category_title = 'Radius' category_header = tr('Distance [km]') category_names = radii name_attribute = 'NAME' # As in e.g. the Smithsonian dataset centers = hazard_layer.get_geometry() rad_m = [x * 1000 for x in radii] # Convert to meters hazard_layer = buffer_points( centers, rad_m, category_title, data_table=data_table) 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 # Get names of volcanoes considered if name_attribute in hazard_layer.get_attribute_names(): volcano_name_list = [] # Run through all polygons and get unique names for row in data_table: volcano_name_list.append(row[name_attribute]) volcano_names = '' for name in volcano_name_list: volcano_names += '%s, ' % name volcano_names = volcano_names[:-2] # Strip trailing ', ' else: volcano_names = tr('Not specified in data') # Check if category_title exists in hazard_layer if category_title not in hazard_layer.get_attribute_names(): msg = ('Hazard data %s did not contain expected ' 'attribute %s ' % (hazard_layer.get_name(), category_title)) # noinspection PyExceptionInherit raise InaSAFEError(msg) # Find the target field name that has no conflict with default target attribute_names = hazard_layer.get_attribute_names() new_target_field = get_non_conflicting_attribute_name( self.target_field, attribute_names) self.target_field = new_target_field # Run interpolation function for polygon2raster interpolated_layer = assign_hazard_values_to_exposure_data( hazard_layer, exposure_layer, attribute_name=self.target_field) # Initialise data_table of output dataset with all data_table # from input polygon and a population count of zero new_data_table = hazard_layer.get_data() categories = {} for row in new_data_table: row[self.target_field] = 0 category = row[category_title] categories[category] = 0 # Count affected population per polygon and total for row in interpolated_layer.get_data(): # Get population at this location population = float(row[self.target_field]) # Update population count for associated polygon poly_id = row['polygon_id'] new_data_table[poly_id][self.target_field] += population # Update population count for each category category = new_data_table[poly_id][category_title] categories[category] += population # Count totals total_population = population_rounding( int(numpy.sum(exposure_layer.get_data(nan=0)))) # Count number and cumulative for each zone cumulative = 0 all_categories_population = {} all_categories_cumulative = {} for name in category_names: if category_title == 'Radius': key = name * 1000 # Convert to meters else: key = name # prevent key error population = int(categories.get(key, 0)) cumulative += population # I'm not sure whether this is the best place to apply rounding? all_categories_population[name] = population_rounding(population) all_categories_cumulative[name] = population_rounding(cumulative) # Use final accumulation as total number needing evacuation evacuated = population_rounding(cumulative) minimum_needs = [ parameter.serialize() for parameter in self.parameters['minimum needs'] ] # Generate impact report for the pdf map blank_cell = '' table_body = [question, TableRow([tr('Volcanoes 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(all_categories_population[name]), format_int(all_categories_cumulative[name])])) table_body.extend([ TableRow(tr( 'Map shows the number of people affected in each of volcano ' 'hazard polygons.'))]) total_needs = evacuated_population_needs( evacuated, minimum_needs) for frequency, needs in total_needs.items(): table_body.append(TableRow( [ tr('Needs should be provided %s' % frequency), tr('Total') ], header=True)) for resource in needs: table_body.append(TableRow([ tr(resource['table name']), format_int(resource['amount'])])) 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_population), tr('People need evacuation if they are within the ' 'volcanic hazard zones.')]) population_counts = [x[self.target_field] for x in new_data_table] 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 per cell)') legend_title = tr('Population') # Create vector layer and return impact_layer = Vector( data=new_data_table, projection=hazard_layer.get_projection(), geometry=hazard_layer.get_geometry(as_geometry_objects=True), name=tr('People 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, 'total_needs': total_needs}, style_info=style_info) return impact_layer
from safe.engine.utilities import buffer_points 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 = buffer_points(center, radius) Z.write_to_file('Marapi_evac_zone_%im.shp' % radius)