def run(layers): """Risk plugin for volcano population impact Input layers: List of layers expected to contain H: Raster layer of volcanic hazard level P: Raster layer of population data on the same grid as H """ # Identify hazard and exposure layers # Volcanic hazard level [0-1] volcanic_hazard_level = get_hazard_layer(layers) population = get_exposure_layer(layers) # Density [people/area] # Extract data as numeric arrays V = volcanic_hazard_level.get_data(nan=0.0) # Population density P = population.get_data(nan=0.0, scaling=True) # Calculate impact as population exposed to depths > threshold I = numpy.where(V > 2.0 / 3, P, 0) # Generate text with result for this study number_of_people_affected = numpy.nansum(I.flat) impact_summary = ('%i people affected by volcanic hazard level greater' ' than 0.667' % number_of_people_affected) # Create raster object and return R = Raster(I, projection=volcanic_hazard_level.get_projection(), geotransform=volcanic_hazard_level.get_geotransform(), name='People affected', keywords={'impact_summary': impact_summary}) return R
def run(layers): """Risk plugin for earthquake fatalities Input layers: List of layers expected to contain H: Raster layer of flood depth P: Raster layer of population data on the same grid as H """ threshold = 1 # Load above which people are regarded affected [kg/m2] # Identify hazard and exposure layers inundation = get_hazard_layer(layers) # Tephra load [kg/m2] population = get_exposure_layer(layers) # Density [people/km^2] # Extract data as numeric arrays D = inundation.get_data(nan=0.0) # Depth P = population.get_data(nan=0.0, scaling=True) # Population density # Calculate impact as population exposed to depths > threshold I = numpy.where(D > threshold, P, 0) # Generate text with result for this study number_of_people_affected = numpy.nansum(I.flat) caption = ('%i people affected by ash levels greater ' 'than %i kg/m^2' % (number_of_people_affected, threshold)) # Create raster object and return R = Raster(I, projection=inundation.get_projection(), geotransform=inundation.get_geotransform(), name='People affected', keywords={'caption': caption}) return R
def run(layers): """Risk plugin for earthquake fatalities Input layers: List of layers expected to contain H: Raster layer of flood depth P: Raster layer of poor household density on the same grid as H """ # Depth above which people are regarded affected [m] threshold = 1.0 # Identify hazard and exposure layers inundation = get_hazard_layer(layers) # Flood inundation [m] poor_households = get_exposure_layer(layers) # Poverty density # Extract data as numeric arrays D = inundation.get_data(nan=0.0) # Depth # This is the new generic way of scaling (issue #168 and #172) P = poor_households.get_data(nan=0.0, scaling=True) I = numpy.where(D > threshold, P, 0) # Generate text with result for this study total = str(int(sum(P.flat) / 1000)) count = str(int(sum(I.flat) / 1000)) # Create report iname = inundation.get_name() pname = poor_households.get_name() impact_summary = ('<b>Apabila terjadi "%s" perkiraan dampak terhadap ' '"%s" kemungkinan yang terjadi:</b><br><br><p>' % (iname, pname)) impact_summary += ('<table border="0" width="320px">') #' <tr><td><b>%s:</b></td>' #'<td align="right"><b>%s</b></td></tr>' #% ('Jumlah Rumah Tangga Miskin', total)) impact_summary += (' <tr><td><b>%s:</b></td>' '<td align="right"><b>%s</b></td></tr>' % ('Jumlah Rumah Tangga Terdampak (x 1000)', count)) impact_summary += '</table>' impact_summary += '<br>' # Blank separation row impact_summary += '<b>Catatan:</b><br>' impact_summary += '- Jumlah Rumah Tangga Miskin %s<br>' % total impact_summary += '- Jumlah dalam ribuan<br>' impact_summary += ('- Rumah Tangga Miskin dalam bahaya ketika ' 'banjir lebih dari %.1f m. ' % threshold) # Create raster object and return R = Raster(I, projection=inundation.get_projection(), geotransform=inundation.get_geotransform(), name='People affected', keywords={'impact_summary': impact_summary}) return R
def run(self, layers): """Risk plugin for tsunami population """ thresholds = [0.2, 0.3, 0.5, 0.8, 1.0] #threshold = 1 # Depth above which people are regarded affected [m] # Identify hazard and exposure layers inundation = get_hazard_layer(layers) # Tsunami inundation [m] population = get_exposure_layer(layers) # Population density # Extract data as numeric arrays D = inundation.get_data(nan=0.0) # Depth P = population.get_data(nan=0.0, scaling=True) # Population density # Calculate impact as population exposed to depths > 1m I_map = numpy.where(D > thresholds[-1], P, 0) # Generate text with result for this study number_of_people_affected = numpy.nansum(I_map.flat) # Do breakdown # Create report impact_summary = ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' % ('Ambang batas', 'Jumlah orang terdampak')) counts = [] for i, threshold in enumerate(thresholds): I = numpy.where(D > threshold, P, 0) counts.append(numpy.nansum(I.flat)) impact_summary += ' <tr><td>%s m</td><td>%i</td></tr>' % ( threshold, counts[i]) impact_summary += '</table>' # Create raster object and return R = Raster(I_map, projection=inundation.get_projection(), geotransform=inundation.get_geotransform(), name='People affected by more than 1m of inundation', keywords={'impact_summary': impact_summary}) return R
def run(layers, teta=14.05, beta=0.17, zeta=2.15): """Risk plugin for earthquake fatalities Input H: Numerical array of hazard data E: Numerical array of exposure data """ # Suppress warnings about invalid value in multiply and divide zero # http://comments.gmane.org/gmane.comp.python.numeric.general/43218 # http://docs.scipy.org/doc/numpy/reference/generated/numpy.seterr.html old_numpy_setting = numpy.seterr(invalid='ignore') numpy.seterr(divide='ignore') # Identify input layers intensity = get_hazard_layer(layers) population = get_exposure_layer(layers) # Extract data H = intensity.get_data(nan=0) P = population.get_data(nan=0) # Calculate impact logHazard = 1 / beta * numpy.log(H / teta) # Convert array to be standard floats expected by cdf arrayout = numpy.array([[float(value) for value in row] for row in logHazard]) x = arrayout * P F = normal_cdf(x) numpy.seterr(**old_numpy_setting) # Create new layer and return R = Raster(F, projection=population.get_projection(), geotransform=population.get_geotransform(), name='Estimated fatalities') return R
def run(layers): """Risk plugin for earthquake school damage """ # Extract data H = get_hazard_layer(layers) # Ground shaking E = get_exposure_layer(layers) # Building locations # Interpolate hazard level to building locations H = H.interpolate(E) # Extract relevant numerical data coordinates = E.get_geometry() shaking = H.get_data() # Calculate building damage building_damage = [] for i in range(len(shaking)): x = float(shaking[i].values()[0]) if x < 6.0: value = 0.0 else: value = (0.692 * (x ** 4) - 15.82 * (x ** 3) + 135.0 * (x ** 2) - 509.0 * x + 714.4) building_damage.append({'DAMAGE': value, 'MMI': x}) # FIXME (Ole): Need helper to generate new layer using # correct spatial reference # (i.e. sensibly wrap the following lines) projection = E.get_projection() V = Vector(data=building_damage, projection=E.get_projection(), geometry=coordinates) return V
def run(layers): """Risk plugin for earthquake fatalities Input layers: List of layers expected to contain H: Raster layer of flood depth P: Raster layer of population data on the same grid as H """ # Depth above which people are regarded affected [m] threshold = 0.1 thresholds = [0.1, 0.2, 0.3, 0.5, 0.8, 1.0] # Identify hazard and exposure layers inundation = get_hazard_layer(layers) # Flood inundation [m] # Get population and gender ratio population = gender_ratio = None for layer in get_exposure_layers(layers): keywords = layer.get_keywords() if 'datatype' not in keywords: population = layer else: datatype = keywords['datatype'] if 'ratio' not in datatype: population = layer else: # if 'female' in datatype and 'ratio' in datatype: gender_ratio_unit = keywords['unit'] msg = ('Unit for gender ratio must be either ' '"percent" or "ratio"') if gender_ratio_unit not in ['percent', 'ratio']: raise Exception(msg) gender_ratio = layer msg = 'No population layer was found in: %s' % str(layers) verify(population is not None, msg) # Extract data as numeric arrays D = inundation.get_data(nan=0.0) # Depth # Calculate impact as population exposed to depths > threshold if population.get_resolution(native=True, isotropic=True) < 0.0005: # Keep this for backwards compatibility just a little while # This uses the original custom population set and # serves as a reference P = population.get_data(nan=0.0) # Population density pixel_area = 2500 I = numpy.where(D > threshold, P, 0) / 100000.0 * pixel_area else: # This is the new generic way of scaling (issue #168 and #172) P = population.get_data(nan=0.0, scaling=True) I = numpy.where(D > threshold, P, 0) if gender_ratio is not None: # Extract gender ratio at each pixel (as ratio) G = gender_ratio.get_data(nan=0.0) if gender_ratio_unit == 'percent': G /= 100 # Calculate breakdown P_female = P * G P_male = P - P_female I_female = I * G I_male = I - I_female # Generate text with result for this study total = str(int(sum(P.flat) / 1000)) count = str(int(sum(I.flat) / 1000)) # Create report impact_summary = ('<table border="0" width="320px">' ' <tr><td><b>%s:</b></td>' '<td align="right"><b>%s</b></td></tr>' % ('Jumlah Penduduk', total)) if gender_ratio is not None: total_female = str(int(sum(P_female.flat) / 1000)) total_male = str(int(sum(P_male.flat) / 1000)) impact_summary += (' <tr><td>%s:</td>' '<td align="right">%s</td></tr>' % (' - Wanita', total_female)) impact_summary += (' <tr><td>%s:</td>' '<td align="right">%s</td></tr>' % (' - Pria', total_male)) impact_summary += '<tr><td> </td></tr>' # Blank row impact_summary += (' <tr><td><b>%s:</b></td>' '<td align="right"><b>%s</b></td></tr>' % ('Perkiraan Jumlah Terdampak (> %.1fm)' % threshold, count)) if gender_ratio is not None: affected_female = str(int(sum(I_female.flat) / 1000)) affected_male = str(int(sum(I_male.flat) / 1000)) impact_summary += (' <tr><td>%s:</td>' '<td align="right">%s</td></tr>' % (' - Wanita', affected_female)) impact_summary += (' <tr><td>%s:</td>' '<td align="right">%s</td></tr>' % (' - Pria', affected_male)) impact_summary += '</table>' impact_summary += '<br>' # Blank separation row impact_summary += 'Catatan: Semua nomor x 1000' # Create raster object and return R = Raster(I, projection=inundation.get_projection(), geotransform=inundation.get_geotransform(), name='People affected', keywords={'impact_summary': impact_summary}) return R
def run(layers, a=0.97429, b=11.037): """Risk plugin for earthquake fatalities Input layers: List of layers expected to contain H: Raster layer of MMI ground shaking P: Raster layer of population data on the same grid as H """ # Identify input layers intensity = get_hazard_layer(layers) # Get population and gender ratio population = gender_ratio = None for layer in get_exposure_layers(layers): keywords = layer.get_keywords() if 'datatype' not in keywords: population = layer else: datatype = keywords['datatype'] if not 'ratio' in datatype: population = layer else: # 'female' in datatype and 'ratio' in datatype: gender_ratio_unit = keywords['unit'] msg = ('Unit for gender ratio must be either ' '"percent" or "ratio"') assert gender_ratio_unit in ['percent', 'ratio'], msg gender_ratio = layer msg = 'No population layer was found in: %s' % str(layers) assert population is not None, msg # Extract data H = intensity.get_data(nan=0) P = population.get_data(nan=0) #print #print 'Population', population.get_name() # Calculate impact F = 10 ** (a * H - b) * P if gender_ratio is not None: # Extract gender ratio at each pixel (as ratio) G = gender_ratio.get_data(nan=0) if gender_ratio_unit == 'percent': G /= 100 # Calculate breakdown P_female = P * G P_male = P - P_female F_female = F * G F_male = F - F_female # Generate text with result for this study count = numpy.nansum(F.flat) total = numpy.nansum(P.flat) # Create report caption = ('<table border="0" width="320px">' ' <tr><td>%s:</td><td>%i</td></tr>' % ('Jumlah Penduduk', int(total))) if gender_ratio is not None: caption += (' <tr><td>%s:</td><td>%i</td></tr>' % (' - Wanita', int(numpy.nansum(P_female.flat)))) caption += (' <tr><td>%s:</td><td>%i</td></tr>' % (' - Pria', int(numpy.nansum(P_male.flat)))) caption += (' <tr><td>%s:</td><td>%i</td></tr>' % ('Perkiraan Orang Meninggal', int(count))) if gender_ratio is not None: caption += (' <tr><td>%s:</td><td>%i</td></tr>' % (' - Wanita', int(numpy.nansum(F_female.flat)))) caption += (' <tr><td>%s:</td><td>%i</td></tr>' % (' - Pria', int(numpy.nansum(F_male.flat)))) caption += '</table>' # Create new layer and return R = Raster(F, projection=population.get_projection(), geotransform=population.get_geotransform(), name='Estimated fatalities', keywords={'caption': caption}) return R
def run(self, layers): """Risk plugin for earthquake school damage """ # Extract data H = get_hazard_layer(layers) # Ground shaking E = get_exposure_layer(layers) # Building locations keywords = E.get_keywords() if 'datatype' in keywords: datatype = keywords['datatype'] if datatype.lower() == 'osm': # Map from OSM attributes to the guideline classes (URM and RM) E = osm2bnpb(E, target_attribute=self.vclass_tag) elif datatype.lower() == 'sigab': # Map from SIGAB attributes to the guideline classes # (URM and RM) E = sigab2bnpb(E) else: E = unspecific2bnpb(E, target_attribute=self.vclass_tag) else: E = unspecific2bnpb(E, target_attribute=self.vclass_tag) # Interpolate hazard level to building locations H = H.interpolate(E) # Extract relevant numerical data coordinates = E.get_geometry() shaking = H.get_data() N = len(shaking) # List attributes to carry forward to result layer attributes = E.get_attribute_names() # Calculate building damage count3 = 0 count2 = 0 count1 = 0 count_unknown = 0 building_damage = [] for i in range(N): mmi = float(shaking[i].values()[0]) building_class = E.get_data(self.vclass_tag, i) lo, hi = damage_parameters[building_class] if numpy.isnan(mmi): # If we don't know the shake level assign Not-a-Number damage = numpy.nan count_unknown += 1 elif mmi < lo: damage = 1 # Low count1 += 1 elif lo <= mmi < hi: damage = 2 # Medium count2 += 1 elif mmi >= hi: damage = 3 # High count3 += 1 else: msg = 'Undefined shakelevel %s' % str(mmi) raise Exception(msg) # Collect shake level and calculated damage result_dict = {self.target_field: damage, 'MMI': mmi} # Carry all orginal attributes forward for key in attributes: result_dict[key] = E.get_data(key, i) # Record result for this feature building_damage.append(result_dict) # Create report caption = ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s (10-25%%):</td><td>%i</td></tr>' ' <tr><td>%s (25-50%%):</td><td>%i</td></tr>' ' <tr><td>%s (50-100%%):</td><td>%i</td></tr>' % (_('Buildings'), _('Total'), _('All'), N, _('Low damage'), count1, _('Medium damage'), count2, _('High damage'), count3)) caption += (' <tr><td>%s (NaN):</td><td>%i</td></tr>' % ('Unknown', count_unknown)) caption += '</table>' # Create style style_classes = [dict(label=_('Low damage'), min=0.5, max=1.5, colour='#fecc5c', transparency=1), dict(label=_('Medium damage'), min=1.5, max=2.5, colour='#fd8d3c', transparency=1), dict(label=_('High damage'), min=2.5, max=3.5, colour='#f31a1c', transparency=1)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return V = Vector(data=building_damage, projection=E.get_projection(), geometry=coordinates, name='Estimated damage level', keywords={'caption': caption}, style_info=style_info) return V
def run(self, layers): """Risk plugin for earthquake fatalities Input layers: List of layers expected to contain H: Raster layer of flood depth P: Raster layer of population data on the same grid as H """ # Depth above which people are regarded affected [m] threshold = 0.1 # Threshold [m] # Identify hazard and exposure layers inundation = get_hazard_layer(layers) # Flood inundation [m] population = get_exposure_layer(layers) # Extract data as numeric arrays D = inundation.get_data(nan=0.0) # Depth # Calculate impact as population exposed to depths > threshold if population.get_resolution(native=True, isotropic=True) < 0.0005: # Keep this for backwards compatibility just a little while # This uses the original custom population set and # serves as a reference P = population.get_data(nan=0.0) # Population density pixel_area = 2500 I = numpy.where(D > threshold, P, 0) / 100000.0 * pixel_area else: # This is the new generic way of scaling (issue #168 and #172) P = population.get_data(nan=0.0, scaling=True) I = numpy.where(D > threshold, P, 0) # Generate text with result for this study total = str(int(numpy.sum(P) / 1000)) count = str(int(numpy.sum(I) / 1000)) # Create report iname = inundation.get_name() pname = population.get_name() impact_summary = ('<table class="table table-striped condensed">') impact_summary += ('<caption>Apabila terjadi "%s" ' 'perkiraan dampak terhadap "%s" ' 'kemungkinan yang terjadi:</caption>' % (iname, pname)) impact_summary += ('<tbody>') impact_summary += (' <tr><th>%s:</th>' '<td align="right">%s</td></tr>' % ('Terdampak (x 1000)', count)) impact_summary += ('</tbody>') impact_summary += '</table>' impact_summary += '<br>' # Blank separation row impact_summary += '<span class="label label-success">' impact_summary += 'Catatan:</span>' impact_summary += '<ul>' impact_summary += ' <li>Jumlah penduduk Jakarta %s</li>' % total impact_summary += ' <li>Jumlah dalam ribuan</li>' impact_summary += (' <li>Penduduk dianggap terdampak ketika ' 'banjir lebih dari %.1f m.</li>' % threshold) impact_summary += '</ul>' impact_table = ('<table class="table table-striped condensed' ' bordered-table">' ' <caption>Jumlah Penduduk Yang Mungkin Dievakuasi</caption>' ' <thead>' ' <tr>' ' <th rowspan="2">Wilayah</th>' ' <th colspan="2">Jumlah Penduduk</th>' ' <th rowspan="2" colspan="2" width="100px">' 'Jumlah Penduduk yang Mungkin dievakuasi</th>' ' </tr>' ' <tr>' ' <th>Perempuan</th>' ' <th>Laki-Laki</th>' ' </tr>' ' </thead>' ' <tbody>' ' <tr>' ' <td>Jakarta Barat</td>' ' <td>87510</td>' ' <td>93076</td>' ' <td>180586</td>' ' </tr>' ' <tr>' ' <td>Jakarta Pusat</td>' ' <td>87510</td>' ' <td>93076</td>' ' <td>180586</td>' ' </tr>' ' <tr>' ' <td>Jakarta Seletan</td>' ' <td>87510</td>' ' <td>93076</td>' ' <td>180586</td>' ' </tr>' ' <tr>' ' <td>Jakarta Timur</td>' ' <td>87510</td>' ' <td>93076</td>' ' <td>180586</td>' ' </tr>' ' <tr>' ' <td>Jakarta Utara</td>' ' <td>87510</td>' ' <td>93076</td>' ' <td>180586</td>' ' </tr>' ' <tr>' ' <td class="align-right">Total</td>' ' <td>87510</td>' ' <td>93076</td>' ' <td>180586</td>' ' </tr>' ' </tbody>' ' <caption>Sumber: Badan Pusat Statistik</caption>' '</table>') map_title = 'Penduduk yang Mungkin dievakuasi' style_info['legend_title'] = 'Kepadatan Penduduk' # Create raster object and return R = Raster(I, projection=inundation.get_projection(), geotransform=inundation.get_geotransform(), name='Penduduk yang %s' % (self.plugin_name.lower()), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title}, style_info=style_info) return R
def run(layers): """Risk plugin for tephra impact """ # Extract data H = get_hazard_layer(layers) # Ash load E = get_exposure_layer(layers) # Building locations # Interpolate hazard level to building locations H = H.interpolate(E, attribute_name="load") # Calculate building damage count3 = 0 count2 = 0 count1 = 0 count0 = 0 result = [] for i in range(len(E)): # ------------------- # Extract parameters # ------------------- load = H.get_data("load", i) # ------------------------ # Compute damage level # ------------------------ # FIXME: The thresholds have been greatly reduced # for the purpose of demonstration. Any real analyis # should bring them back to 0, 90, 150, 300 if 0.01 <= load < 0.5: # Loss of crops and livestock impact = 0 count0 += 1 elif 0.5 <= load < 2.0: # Cosmetic damage impact = 1 count1 += 1 elif 2.0 <= load < 10.0: # Partial building collapse impact = 2 count2 += 1 elif load >= 10.0: # Complete building collapse impact = 3 count3 += 1 else: impact = 0 count0 += 1 result.append({"DAMAGE": impact, "ASHLOAD": load}) # Create report impact_summary = ( '<font size="3"> <table border="0" width="320px">' " <tr><th><b>%s</b></th><th><b>%s</b></th></th>" " <tr></tr>" " <tr><td>%s:</td><td>%i</td></tr>" " <tr><td>%s:</td><td>%i</td></tr>" " <tr><td>%s:</td><td>%i</td></tr>" " <tr><td>%s:</td><td>%i</td></tr>" "</table></font>" % ( "Beban abu", "Gedung dampak", "< 0.5 kg/m2", count0, "0.5 - 2 kg/m2", count1, "2 - 10 kg/m2", count2, "> 10 kg/m2", count3, ) ) #'</table>' % # ('Beban abu', 'Gedung dampak', # 'Gangguan (< 90 kg/m2)', count0, # 'Kerusakan kosmetik (90 - 150 kg/m2', count1, # 'parsial runtuhnya (150 - 300 kg/m2', count2, # 'runtuhnya lengkap (> 300 kg/m2', count3)) V = Vector( data=result, projection=E.get_projection(), geometry=E.get_geometry(), name="Estimated ashload damage", keywords={"impact_summary": impact_summary}, ) return V
def run(self, layers): """Risk plugin for tsunami population """ threshold = 1.0 # Flood threshold [m] # Extract data H = get_hazard_layer(layers) # Depth E = get_exposure_layer(layers) # Building locations # FIXME (Ole): interpolate does not carry original name through, # so get_name gives "Vector Layer" :-) # Interpolate hazard level to building locations I = H.interpolate(E) # Extract relevant numerical data attributes = I.get_data() N = len(I) # List attributes to carry forward to result layer attribute_names = E.get_attribute_names() # Calculate population impact count = 0 building_impact = [] for i in range(N): if H.is_raster: # Get the interpolated depth x = float(attributes[i].values()[0]) x = x > threshold elif H.is_vector: # Use interpolated polygon attribute x = attributes[i]['Affected'] # Tag and count if x is True: affected = 1 count += 1 else: affected = 0 # Collect depth and calculated damage result_dict = {self.target_field: x} # Carry all original attributes forward # FIXME (Ole): Make this part of the interpolation (see issue #101) for key in attribute_names: result_dict[key] = E.get_data(key, i) # Record result for this feature building_impact.append(result_dict) # Create report Hname = H.get_name() Ename = E.get_name() caption = _('<b>In case of "%s" the estimated impact to "%s" ' 'the possibility of :</b><br><br><p>' % (Hname, Ename)) caption += ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s :</td><td>%i</td></tr>' ' <tr><td>%s :</td><td>%i</td></tr>' ' <tr><td>%s :</td><td>%i</td></tr>' '</table>' % (_('Building'), _('Number of'), _('All'), N, _('Closed'), count, _('Opened'), N - count)) caption += '<br>' # Blank separation row caption += '<b>' + _('Assumption') + ':</b><br>' caption += _('Buildings that will need to closed when flooding' 'more than %.1f m' % threshold) # Create style style_classes = [dict(label=_('Opened'), min=0, max=0, colour='#1EFC7C', transparency=0), dict(label=_('Closed'), min=1, max=1, colour='#F31A1C', transparency=0)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return V = Vector(data=building_impact, projection=E.get_projection(), geometry=E.get_geometry(), name=_('Estimated buildings affected'), keywords={'caption': caption}, style_info=style_info) return V
def run(self, layers): """Risk plugin for tsunami population """ # Extract data H = get_hazard_layer(layers) # Depth E = get_exposure_layer(layers) # Building locations # Interpolate hazard level to building locations Hi = H.interpolate(E) # Extract relevant numerical data coordinates = Hi.get_geometry() depth = Hi.get_data() N = len(depth) # List attributes to carry forward to result layer attributes = E.get_attribute_names() # Calculate building impact according to guidelines count3 = 0 count1 = 0 count0 = 0 population_impact = [] for i in range(N): if H.is_raster: # Get depth dep = float(depth[i].values()[0]) # Classify buildings according to depth if dep >= 3: affected = 3 # FIXME: Colour upper bound is 100 but count3 += 1 # does not catch affected == 100 elif 1 <= dep < 3: affected = 2 count1 += 1 else: affected = 1 count0 += 1 elif H.is_vector: dep = 0 # Just put something here cat = depth[i]['Affected'] if cat is True: affected = 3 count3 += 1 else: affected = 1 count0 += 1 # Collect depth and calculated damage result_dict = {self.target_field: affected, 'DEPTH': dep} # Carry all original attributes forward # FIXME: This should be done in interpolation. Check. #for key in attributes: # result_dict[key] = E.get_data(key, i) # Record result for this feature population_impact.append(result_dict) # Create report if H.is_raster: impact_summary = ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % ('ketinggian tsunami', 'Jumlah gedung', '< 1 m', count0, '1 - 3 m', count1, '> 3 m', count3)) else: impact_summary = ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % ('Terdampak oleh tsunami', 'Jumlah gedung', 'Terdampak', count3, 'Tidak terdampak', count0, 'Semua', N)) # Create style style_classes = [dict(label=_('OK'), min=0, max=2, colour='#1EFC7C', transparency=0), dict(label=_('Flooded'), min=2, max=4, colour='#F31A1C', transparency=0)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return if Hi.is_line_data: name = 'Roads flooded' elif Hi.is_point_data: name = 'Buildings flooded' V = Vector(data=population_impact, projection=E.get_projection(), geometry=coordinates, keywords={'impact_summary': impact_summary}, geometry_type=Hi.geometry_type, name=name, style_info=style_info) return V
def run(self, layers): """Separate exposed elements by depth [m]: < 1 Rendah 1 - 3 Sedang > 3 Tinggi """ # Extract data H = get_hazard_layer(layers) # Depth E = get_exposure_layer(layers) # Building locations # Interpolate hazard level to building locations I = H.interpolate(E, attribute_name='depth') # Extract relevant numerical data attributes = I.get_data() N = len(I) # List attributes to carry forward to result layer attribute_names = E.get_attribute_names() # Calculate building impact rendah = 0 sedang = 0 tinggi = 0 building_impact = [] for i in range(N): # Get the interpolated depth x = float(attributes[i]['depth']) # Assign impact level (nilai) depending on depth and count if x < 1: nilai = 1 rendah += 1 elif 1 <= x < 3: nilai = 2 sedang += 1 else: nilai = 3 tinggi += 1 # Record depth and impact level for this feature building_impact.append({'depth': x, self.target_field: nilai}) # Create summary report Hname = H.get_name() Ename = E.get_name() table = ('<b>In case of "%s" the estimated impact to "%s" ' 'the possibility of :</b><br><br><p>' % (Hname, Ename)) table += ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s :</td><td>%i</td></tr>' ' <tr><td>%s :</td><td>%i</td></tr>' ' <tr><td>%s :</td><td>%i</td></tr>' ' <tr><td>%s :</td><td>%i</td></tr>' '</table>' % (('Ketinggian Banjir'), ('Jumlah gedung'), ('All'), N, ('< 1 m'), rendah, ('1 - 3 m'), sedang, ('> 3 m'), tinggi)) table += '<br>' # Blank separation row table += '<b>' + ('Based on BNPB Perka 2 - 2012') + '</b><br>' # Create style style_classes = [dict(label=('< 1 m'), min=1, max=1, colour='#00FF00', # Green transparency=0, size=1), dict(label=('1 - 3 m'), min=2, max=2, colour='#FFFF00', # Yellow transparency=0, size=1), dict(label=('> 3 m'), min=3, max=3, colour='#FF0000', # Red transparency=0, size=1)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return V = Vector(data=building_impact, projection=E.get_projection(), geometry=E.get_geometry(), name=('Estimated buildings affected'), keywords={'impact_summary': table}, style_info=style_info) return V
def run(self, layers, x=0.62275231, y=8.03314466, zeta=2.15): """Indonesian Earthquake Fatality Model Input layers: List of layers expected to contain H: Raster layer of MMI ground shaking P: Raster layer of population density """ # Define percentages of people being displaced at each mmi level displacement_rate = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0.1, 8: 0.5, 9: 0.75, 10: 1.0} # Extract input layers intensity = get_hazard_layer(layers) population = get_exposure_layer(layers) question = get_question(intensity.get_name(), population.get_name(), self) # Extract data grids H = intensity.get_data() # Ground Shaking P = population.get_data() # Population Density # Calculate population affected by each MMI level # FIXME (Ole): this range is 2-9. Should 10 be included? mmi_range = range(2, 10) number_of_exposed = {} number_of_displaced = {} number_of_fatalities = {} # Calculate fatality rates for observed Intensity values (H # based on ITB power model R = numpy.zeros(H.shape) for mmi in mmi_range: # Identify cells where MMI is in class i mask = (H > mmi - 0.5) * (H <= mmi + 0.5) # Count population affected by this shake level I = numpy.where(mask, P, 0) # Calculate expected number of fatalities per level fatality_rate = numpy.power(10.0, x * mmi - y) F = fatality_rate * I # Calculate expected number of displaced people per level try: D = displacement_rate[mmi] * I except Exception, e: msg = 'mmi = %i, I = %s, Error msg: %s' % (mmi, str(I), str(e)) fid = open('C:\\error_message.txt', 'wb') fid.write(msg) fid.close() # Sum up numbers for map R += F # Fatalities #R += D # Displaced # Generate text with result for this study # This is what is used in the real time system exposure table number_of_exposed[mmi] = numpy.nansum(I.flat) number_of_displaced[mmi] = numpy.nansum(D.flat) number_of_fatalities[mmi] = numpy.nansum(F.flat)
def run(self, layers): """Risk plugin for earthquake fatalities Input layers: List of layers expected to contain H: Raster layer of flood depth P: Raster layer of population data on the same grid as H """ # Depth above which people are regarded affected [m] threshold = 1.5 # Threshold [m] # Identify hazard and exposure layers inundation = get_hazard_layer(layers) # Flood inundation [m] population = get_exposure_layer(layers) # Extract data as numeric arrays D = inundation.get_data(nan=0.0) # Depth # Calculate impact as population exposed to depths > threshold if population.get_resolution(native=True, isotropic=True) < 0.0005: # Keep this for backwards compatibility just a little while # This uses the original custom population set and # serves as a reference P = population.get_data(nan=0.0) # Population density pixel_area = 2500 I = numpy.where(D > threshold, P, 0) / 100000.0 * pixel_area else: # This is the new generic way of scaling (issue #168 and #172) P = population.get_data(nan=0.0, scaling=True) I = numpy.where(D > threshold, P, 0) # Generate text with result for this study total = str(int(numpy.sum(P) / 1000)) count = str(int(numpy.sum(I) / 1000)) # Create report iname = inundation.get_name() pname = population.get_name() impact_summary = ('<b>Apabila terjadi "%s" perkiraan dampak ' 'terhadap "%s" kemungkinan yang terjadi:' '</b><br><br><p>' % (iname, pname)) impact_summary += ('<table border="0" width="320px">') impact_summary += (' <tr><td><b>%s:</b></td>' '<td align="right"><b>%s</b></td></tr>' % ('Meninggal (x 1000)', count)) impact_summary += '</table>' impact_summary += '<br>' # Blank separation row impact_summary += '<b>Catatan:</b><br>' impact_summary += '- Jumlah penduduk Jakarta %s<br>' % total impact_summary += '- Jumlah dalam ribuan<br>' impact_summary += ('- Penduduk dianggap meninggal ketika ' 'banjir lebih dari %.1f m.' % threshold) # Create raster object and return R = Raster(I, projection=inundation.get_projection(), geotransform=inundation.get_geotransform(), name='Penduduk yang %s' % (self.plugin_name.lower()), keywords={'impact_summary': impact_summary}, style_info=style_info) return R
def run(self, layers): """Risk plugin for earthquake fatalities Input layers: List of layers expected to contain H: Raster layer of flood depth P: Raster layer of population data on the same grid as H """ # Depth above which people are regarded affected [m] threshold = 1.0 # Threshold [m] # Identify hazard and exposure layers inundation = get_hazard_layer(layers) # Flood inundation [m] # Get population and gender ratio population = gender_ratio = None for layer in get_exposure_layers(layers): keywords = layer.get_keywords() if 'datatype' not in keywords: population = layer else: datatype = keywords['datatype'] if 'ratio' not in datatype: population = layer else: #if 'female' in datatype and 'ratio' in datatype: gender_ratio_unit = keywords['unit'] msg = ('Unit for gender ratio must be either ' '"percent" or "ratio"') assert gender_ratio_unit in ['percent', 'ratio'], msg gender_ratio = layer msg = 'No population layer was found in: %s' % str(layers) assert population is not None, msg # Extract data as numeric arrays D = inundation.get_data(nan=0.0) # Depth # Calculate impact as population exposed to depths > threshold if population.get_resolution(native=True, isotropic=True) < 0.0005: # Keep this for backwards compatibility just a little while # This uses the original custom population set and # serves as a reference P = population.get_data(nan=0.0) # Population density pixel_area = 2500 I = numpy.where(D > threshold, P, 0) / 100000.0 * pixel_area else: # This is the new generic way of scaling (issue #168 and #172) P = population.get_data(nan=0.0, scaling=True) I = numpy.where(D > threshold, P, 0) if gender_ratio is not None: # Extract gender ratio at each pixel (as ratio) G = gender_ratio.get_data(nan=0.0) if gender_ratio_unit == 'percent': G /= 100 # Calculate breakdown P_female = P * G P_male = P - P_female I_female = I * G I_male = I - I_female # Generate text with result for this study total = str(int(numpy.sum(P) / 1000)) count = str(int(numpy.sum(I) / 1000)) # Create report iname = inundation.get_name() pname = population.get_name() caption = ('<b>Apabila terjadi "%s" perkiraan dampak terhadap "%s" ' 'kemungkinan yang terjadi:</b><br><br><p>' % (iname, pname)) caption += ('<table border="0" width="320px">') #' <tr><td><b>%s:</b></td>' #'<td align="right"><b>%s</b></td></tr>' #% ('Jumlah Penduduk', total)) # if gender_ratio is not None: # total_female = str(int(sum(P_female.flat) / 1000)) # total_male = str(int(sum(P_male.flat) / 1000)) # caption += (' <tr><td>%s:</td>' # '<td align="right">%s</td></tr>' # % (' - Wanita', total_female)) # caption += (' <tr><td>%s:</td>' # '<td align="right">%s</td></tr>' # % (' - Pria', total_male)) # caption += '<tr><td> </td></tr>' # Blank separation row caption += (' <tr><td><b>%s:</b></td>' '<td align="right"><b>%s</b></td></tr>' % ('Perlu Evakuasi (x 1000)', count)) if gender_ratio is not None: affected_female = str(int(sum(I_female.flat) / 1000)) affected_male = str(int(sum(I_male.flat) / 1000)) caption += (' <tr><td>%s:</td>' '<td align="right">%s</td></tr>' % (' - Wanita', affected_female)) caption += (' <tr><td>%s:</td>' '<td align="right">%s</td></tr>' % (' - Pria', affected_male)) caption += '</table>' caption += '<br>' # Blank separation row caption += '<b>Catatan:</b><br>' caption += '- Jumlah penduduk Jakarta %s<br>' % total caption += '- Jumlah dalam ribuan<br>' caption += ('- Penduduk dianggap perlu dievakuasi ketika ' 'banjir lebih dari %.1f m.' % threshold) # Create raster object and return R = Raster(I, projection=inundation.get_projection(), geotransform=inundation.get_geotransform(), name='Penduduk yang %s' % (self.plugin_name.lower()), keywords={'caption': caption}) return R
def run(self, layers): """Risk plugin for Padang building survey """ # Extract data H = get_hazard_layer(layers) # Ground shaking E = get_exposure_layer(layers) # Building locations datatype = E.get_keywords()['datatype'] if datatype.lower() == 'osm': # Map from OSM attributes to the padang building classes E = osm2padang(E) vclass_tag = 'VCLASS' elif datatype.lower() == 'sigab': E = sigab2padang(E) vclass_tag = 'VCLASS' else: vclass_tag = 'TestBLDGCl' # Interpolate hazard level to building locations H = H.interpolate(E) # Extract relevant numerical data coordinates = E.get_geometry() shaking = H.get_data() N = len(shaking) # List attributes to carry forward to result layer attributes = E.get_attribute_names() # Calculate building damage count50 = 0 count25 = 0 count10 = 0 count0 = 0 building_damage = [] for i in range(N): mmi = float(shaking[i].values()[0]) building_class = E.get_data(vclass_tag, i) building_type = str(int(building_class)) damage_params = damage_curves[building_type] beta = damage_params['beta'] median = damage_params['median'] percent_damage = cdf(mmi, mu=median, sigma=beta) * 100 # Collect shake level and calculated damage result_dict = {self.target_field: percent_damage, 'MMI': mmi} # Carry all orginal attributes forward for key in attributes: result_dict[key] = E.get_data(key, i) # Record result for this feature building_damage.append(result_dict) # Calculate statistics if percent_damage < 10: count0 += 1 if 10 <= percent_damage < 25: count10 += 1 if 25 <= percent_damage < 50: count25 += 1 if 50 <= percent_damage: count50 += 1 # Create report caption = ('<font size="3"> <table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s (<10%%):</td><td>%i</td></tr>' ' <tr><td>%s (10-25%%):</td><td>%i</td></tr>' ' <tr><td>%s (25-50%%):</td><td>%i</td></tr>' ' <tr><td>%s (50-100%%):</td><td>%i</td></tr>' '</table></font>' % (_('Buildings'), _('Total'), _('All'), N, _('No damage'), count0, _('Low damage'), count10, _('Medium damage'), count25, _('High damage'), count50)) # Create vector layer and return V = Vector(data=building_damage, projection=E.get_projection(), geometry=coordinates, name='Estimated pct damage', keywords={'caption': caption}) return V
def run(self, layers): """Risk plugin for Padang building survey """ # Extract data H = get_hazard_layer(layers) # Ground shaking E = get_exposure_layer(layers) # Building locations datatype = E.get_keywords()['datatype'] vclass_tag = 'VCLASS' if datatype.lower() == 'osm': # Map from OSM attributes to the padang building classes Emap = osm2padang(E) elif datatype.lower() == 'sigab': Emap = sigab2padang(E) elif datatype.lower() == 'padang': Emap = padang2itb(E) else: Emap = E # Interpolate hazard level to building locations Hi = H.interpolate(Emap, attribute_name='MMI') # Extract relevant numerical data coordinates = Emap.get_geometry() shaking = Hi.get_data() N = len(shaking) # List attributes to carry forward to result layer attributes = Emap.get_attribute_names() # Calculate building damage count50 = 0 count25 = 0 count10 = 0 count0 = 0 building_damage = [] for i in range(N): mmi = float(shaking[i]['MMI']) building_class = Emap.get_data(vclass_tag, i) building_type = str(int(building_class)) damage_params = damage_curves[building_type] beta = damage_params['beta'] median = damage_params['median'] percent_damage = lognormal_cdf(mmi, median=median, sigma=beta) * 100 # Collect shake level and calculated damage result_dict = {self.target_field: percent_damage, 'MMI': mmi} # Carry all orginal attributes forward for key in attributes: result_dict[key] = Emap.get_data(key, i) # Record result for this feature building_damage.append(result_dict) # Debugging #if percent_damage > 0.01: # print mmi, percent_damage # Calculate statistics if percent_damage < 10: count0 += 1 if 10 <= percent_damage < 33: count10 += 1 if 33 <= percent_damage < 66: count25 += 1 if 66 <= percent_damage: count50 += 1 # Create report Hname = H.get_name() Ename = E.get_name() impact_summary = ('<b>In case of "%s" the estimated impact to ' '"%s" ' 'is:</b><br><br><p>' % (Hname, Ename)) impact_summary += ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s (<10%%):</td><td>%i</td></tr>' ' <tr><td>%s (10-33%%):</td><td>%i</td></tr>' ' <tr><td>%s (33-66%%):</td><td>%i</td></tr>' ' <tr><td>%s (66-100%%):</td><td>%i</td></tr>' '</table></font>' % (_('Buildings'), _('Total'), _('All'), N, _('No damage'), count0, _('Low damage'), count10, _('Medium damage'), count25, _('High damage'), count50)) impact_summary += '<br>' # Blank separation row impact_summary += '<b>' + _('Assumption') + ':</b><br>' # This is the proper text: #_('Levels of impact are defined by post 2009 ' # 'Padang earthquake survey conducted by Geoscience ' # 'Australia and Institute of Teknologi Bandung.')) #_('Unreinforced masonry is assumed where no ' # 'structural information is available.')) impact_summary += _('Levels of impact are defined by post 2009 ' 'Padang earthquake survey conducted by Geoscience ' 'Australia and Institute of Teknologi Bandung.') impact_summary += _('Unreinforced masonry is assumed where no ' 'structural information is available.') # Create style style_classes = [dict(label=_('No damage'), min=0, max=10, colour='#00ff00', transparency=1), dict(label=_('Low damage'), min=10, max=33, colour='#ffff00', transparency=1), dict(label=_('Medium damage'), min=33, max=66, colour='#ffaa00', transparency=1), dict(label=_('High damage'), min=66, max=100, colour='#ff0000', transparency=1)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return V = Vector(data=building_damage, projection=E.get_projection(), geometry=coordinates, name='Estimated pct damage', keywords={'impact_summary': impact_summary}, style_info=style_info) return V
def run(layers): """Calculate population exposed to different levels of ground shaking Input layers: List of layers expected to contain H: Raster layer of MMI ground shaking P: Raster layer of population density """ # Identify input layers intensity = get_hazard_layer(layers) population = get_exposure_layer(layers) # Extract data H = intensity.get_data(nan=0) P = population.get_data(nan=0) # Calculate exposure to MMI impact mmi_classes = range(1, 11) # MMI classes considered (1-10) # Form result as keyword strings mmi_str = str(mmi_classes)[1:-1] # Get rid of [] count_str = '' for i in mmi_classes: # Identify cells where MMI is in class i mask = (H >= i - 0.5) * (H < i + 0.5) # Count population affected by this shake level count = round(numpy.nansum(P[mask])) if numpy.isnan(count): count = 0 # Update keyword string count_str += '%i ' % count # Calculate fatality map (FIXME (Ole): Need to replaced by USGS model) a = 0.97429 b = 11.037 F = 10 ** (a * H - b) * P # Generate text with result for this study count = numpy.nansum(F.flat) total = numpy.nansum(P.flat) # Create report caption = ('<table border="0" width="320px">' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % ('Jumlah Penduduk', int(total), 'Perkiraan Orang Meninggal', int(count))) # Create new layer and return R = Raster(F, projection=population.get_projection(), geotransform=population.get_geotransform(), name='Estimated fatalities', keywords={'caption': caption, 'mmi-classes': mmi_str, 'affected-population': count_str}) return R
def run(self, layers): """Risk plugin for flood population evacuation Input layers: List of layers expected to contain H: Raster layer of flood 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 """ # Depth above which people are regarded affected [m] threshold = 1.0 # Threshold [m] # Identify hazard and exposure layers inundation = get_hazard_layer(layers) # Flood inundation [m] population = get_exposure_layer(layers) question = get_question(inundation.get_name(), population.get_name(), self) # Extract data as numeric arrays D = inundation.get_data(nan=0.0) # Depth # Calculate impact as population exposed to depths > threshold P = population.get_data(nan=0.0, scaling=True) I = numpy.where(D > threshold, P, 0) M = numpy.where(D > 0.5, P, 0) L = numpy.where(D > 0.3, P, 0) # Count totals total = int(numpy.sum(P)) evacuated = int(numpy.sum(I)) medium = int(numpy.sum(M)) - int(numpy.sum(I)) low = int(numpy.sum(L)) - int(numpy.sum(M)) # Don't show digits less than a 1000 if total > 1000: total = total // 1000 * 1000 if evacuated > 1000: evacuated = evacuated // 1000 * 1000 if medium > 1000: medium = medium // 1000 * 1000 if low > 1000: low = low // 1000 * 1000 # Calculate estimated needs based on BNPB Perka 7/2008 minimum bantuan rice = evacuated * 2.8 drinking_water = evacuated * 17.5 water = evacuated * 67 family_kits = evacuated / 5 toilets = evacuated / 20 # Generate impact report for the pdf map table_body = [question, TableRow([_('People needing evacuation'), '%i' % evacuated], header=True), TableRow(_('Map shows population density needing ' 'evacuation'))] #, ## TableRow([_('People in 50cm to 1m of water '), ## '%i' % medium], ## header=True), ## TableRow([_('People in 30cm to 50cm of water'), ## '%i' % low], ## header=True)] ## TableRow([_('Needs per week'), _('Total')], ## header=True), ## [_('Rice [kg]'), int(rice)], ## [_('Drinking Water [l]'), int(drinking_water)], ## [_('Clean Water [l]'), int(water)], ## [_('Family Kits'), int(family_kits)], ## [_('Toilets'), int(toilets)]] impact_table = Table(table_body).toNewlineFreeString() # Extend impact report for on-screen display table_body.extend([TableRow(_('Notes:'), header=True), _('Total population: %i') % total, _('People need evacuation if flood levels ' 'exceed %(eps)i m') % {'eps': threshold}, _('People in 50cm to 1m of water: %i') % medium, _('People in 30cm to 50cm of water: %i') % low]) ## _('Minimum needs are defined in BNPB ' ## 'regulation 7/2008')]) impact_summary = Table(table_body).toNewlineFreeString() map_title = _('People in need of evacuation') style_info['legend_title'] = _('Population Density') # Create raster object and return R = Raster(I, projection=inundation.get_projection(), geotransform=inundation.get_geotransform(), name=_('Population which %s') % get_function_title(self), keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title}, style_info=style_info) return R
def run(self, layers, x=0.62275231, y=8.03314466, zeta=2.15): """Gender specific earthquake impact model Input layers: List of layers expected to contain H: Raster layer of MMI ground shaking P: Raster layer of population density """ # Define percentages of people being displaced at each mmi level displacement_rate = {1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0.1, 8: 0.5, 9: 0.75, 10: 1.0} # Extract input layers intensity = get_hazard_layer(layers) population = get_exposure_layer(layers) question = get_question(intensity.get_name(), population.get_name(), self) # Extract data grids H = intensity.get_data() # Ground Shaking P = population.get_data() # Population Density # Calculate population affected by each MMI level # FIXME (Ole): this range is 2-9. Should 10 be included? mmi_range = range(2, 10) number_of_exposed = {} number_of_fatalities = {} # Calculate fatality rates for observed Intensity values (H # based on ITB power model R = numpy.zeros(H.shape) for mmi in mmi_range: # Identify cells where MMI is in class i mask = (H > mmi - 0.5) * (H <= mmi + 0.5) # Count population affected by this shake level I = numpy.where(mask, P, 0) # Calculate expected number of fatalities per level fatality_rate = numpy.power(10.0, x * mmi - y) F = fatality_rate * I # Sum up fatalities to create map R += F # Generate text with result for this study # This is what is used in the real time system exposure table number_of_exposed[mmi] = numpy.nansum(I.flat) number_of_fatalities[mmi] = numpy.nansum(F.flat) # Set resulting layer to zero when less than a threshold. This is to # achieve transparency (see issue #126). R[R < 1] = numpy.nan # Total statistics total = numpy.nansum(P.flat) # Compute number of fatalities fatalities = numpy.nansum(number_of_fatalities.values()) # Compute number of people displaced due to building collapse displaced = 0 for mmi in mmi_range: displaced += displacement_rate[mmi] * number_of_exposed[mmi] displaced_women = displaced * 0.52 # Could be made province dependent displaced_pregnant_women = displaced_women * 0.01387 # CHECK # Generate impact report table_body = [question] # Add total fatality estimate s = str(int(fatalities)).rjust(10) table_body.append(TableRow([_("Number of fatalities"), s], header=True)) # Add total estimate of people displaced s = str(int(displaced)).rjust(10) table_body.append(TableRow([_("Number of people displaced"), s], header=True)) s = str(int(displaced_women)).rjust(10) table_body.append(TableRow([_("Number of women displaced"), s], header=True)) s = str(int(displaced_pregnant_women)).rjust(10) table_body.append(TableRow([_("Number of pregnant women displaced"), s], header=True)) table_body.append(TableRow(_("Action Checklist:"), header=True)) table_body.append(_("Are enough shelters available for %i women?") % displaced_women) table_body.append( _("Are enough facilities available to assist %i " "pregnant women?") % displaced_pregnant_women ) table_body.append(TableRow(_("Notes:"), header=True)) table_body.append(_("Fatality model is from " "Institute of Teknologi Bandung 2012.")) impact_summary = Table(table_body).toNewlineFreeString() impact_table = impact_summary map_title = _("Earthquake impact to population") # Create new layer and return L = Raster( R, projection=population.get_projection(), geotransform=population.get_geotransform(), keywords={ "impact_summary": impact_summary, "total_population": total, "total_fatalities": fatalities, "impact_table": impact_table, "map_title": map_title, }, name=_("Estimated fatalities"), style_info=style_info, ) # Maybe return a shape file with contours instead return L
def run(layers, teta=14.05, beta=0.17, zeta=2.15): """Risk plugin for earthquake fatalities Input H: Numerical array of hazard data E: Numerical array of exposure data Algorithm and coefficients are from: An Empirical Model for Global Earthquake Fatality Estimation. Kishor Jaiswal and David Wald. Earthquake Spectra, Volume 26, No. 4, pages 1017-1037, November 2010. teta=14.05, beta=0.17, zeta=2.1 # Coefficients for Indonesia. """ # Identify input layers intensity = get_hazard_layer(layers) population = get_exposure_layer(layers) print intensity.get_resolution() print population.get_resolution() # Extract data H = intensity.get_data(nan=0) # Ground Shaking P = population.get_data(nan=0) # Population Density import cPickle name = intensity.get_name() print name fid = open('/home/nielso/population_%s.pck' % name, 'wb') cPickle.dump(P, fid) fid.close() fid = open('/home/nielso/intensity_%s.pck' % name, 'wb') cPickle.dump(H, fid) fid.close() # Calculate population affected by each MMI level mmi_range = range(2, 10) number_of_people_affected = {} for mmi in mmi_range: mask = numpy.logical_and(mmi - 0.5 < H, H <= mmi + 0.5) I = numpy.where(mask, P, 0) # Generate text with result for this study number_of_people_affected[mmi] = numpy.nansum(I.flat) # Calculate impact according to equation (1) in the # Kishor and Wald 2010 logHazard = 1 / beta * numpy.log(H / teta) # Convert array to be standard floats expected by cdf arrayout = numpy.array([[float(value) for value in row] for row in logHazard]) F = cdf(arrayout * P) # Stats total = numpy.nansum(P.flat) fatalities = numpy.nansum(F) print 'Total', total print 'Estimated fatalities', fatalities print 'Min', numpy.amin(F) print 'Max', numpy.amax(F) # Generate text with result for this study caption = generate_exposure_table(mmi_range, number_of_people_affected) caption += generate_fatality_table(fatalities) # Create new layer and return R = Raster(F, projection=population.get_projection(), geotransform=population.get_geotransform(), keywords={'caption': caption}, name='Estimated fatalities') return R
def run(self, layers, a=0.97429, b=11.037): """Risk plugin for earthquake fatalities Input layers: List of layers expected to contain H: Raster layer of MMI ground shaking E: Polygon population data a: Parameter for Allen impact function b: Parameter for Allen impact function """ # Identify input layers H = get_hazard_layer(layers) # Intensity E = get_exposure_layer(layers) # Exposure - population counts # Interpolate hazard level to building locations H = H.interpolate(E) # Extract relevant numerical data coordinates = E.get_geometry() # Stay with polygons shaking = H.get_data() N = len(shaking) # List attributes to carry forward to result layer attributes = E.get_attribute_names() # Calculate fatilities count = 0 total = 0 result_feature_set = [] for i in range(N): mmi = float(shaking[i].values()[0]) if mmi < 0.0: # FIXME: Hack until interpolation is fixed mmi = 0.0 population_count = E.get_data('Jumlah_Pen', i) # Calculate impact F = 10 ** (a * mmi - b) * population_count # Collect shake level and calculated damage result_dict = {self.target_field: F, 'MMI': mmi} # Carry all orginal attributes forward for key in attributes: result_dict[key] = E.get_data(key, i) # Record result for this feature result_feature_set.append(result_dict) # Calculate statistics if not numpy.isnan(F): count += F total += population_count # Create report impact_summary = ('<table border="0" width="320px">' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % ('Jumlah Penduduk', int(total), 'Perkiraan Orang Meninggal', int(count))) # Create vector layer and return V = Vector(data=result_feature_set, projection=E.get_projection(), geometry=coordinates, name='Estimated fatalities', keywords={'impact_summary': impact_summary}) return V
def run(layers): """Risk plugin for tsunami building damage """ # Extract data H = get_hazard_layer(layers) # Ground shaking E = get_exposure_layer(layers) # Building locations # Interpolate hazard level to building locations H = H.interpolate(E, attribute_name='depth') # Extract relevant numerical data coordinates = E.get_geometry() inundation = H.get_data() # Calculate N = len(H) impact = [] for i in range(N): #------------------- # Extract parameters #------------------- depth = float(inundation[i]['depth']) shore_distance = E.get_data('SHORE_DIST', i) # FIXME: Get rid of the type casting when # issue #66 is done number_of_people_in_building = int(E.get_data('NEXIS_PEOP', i)) wall_type = E.get_data('WALL_TYPE', i) contents_value = E.get_data('CONT_VALUE', i) structure_value = E.get_data('STR_VALUE', i) #------------------------ # Compute people affected #------------------------ if 0.01 < depth < 1.0: people_affected = number_of_people_in_building else: people_affected = 0 if depth >= 1.0: people_severely_affected = number_of_people_in_building else: people_severely_affected = 0 #---------------------------------------- # Compute impact on buldings and contents #---------------------------------------- depth_floor = depth - 0.3 # Adjust for floor height if depth_floor >= 0.0: buildings_inundated = 1 else: buildings_inundated = 0 if depth_floor < 0.0: structural_damage = contents_damage = 0.0 else: # Water is deep enough to cause damage if wall_type in struct_damage_curve: curve = struct_damage_curve[wall_type] else: # Establish default for unknown wall type curve = struct_damage_curve['Brick veneer'] structural_damage = curve(depth_floor) contents_damage = contents_damage_curve(depth_floor) #--------------- # Compute losses #--------------- structural_loss = structural_damage * structure_value contents_loss = contents_damage * contents_value #------- # Return #------- impact.append({'NEXIS_PEOP': number_of_people_in_building, 'PEOPLE_AFFECTED': people_affected, 'PEOPLE_SEV_AFFECTED': people_severely_affected, 'STRUCT_INUNDATED': buildings_inundated, 'STRUCT_DAMAGE_fraction': structural_damage, 'CONTENTS_DAMAGE_fraction': contents_damage, 'STRUCT_LOSS_AUD': structural_loss, 'CONTENTS_LOSS_AUD': contents_loss, 'DEPTH': depth}) # FIXME (Ole): Need helper to generate new layer using # correct spatial reference # (i.e. sensibly wrap the following lines) V = Vector(data=impact, projection=E.get_projection(), geometry=coordinates, name='Estimated tsunami impact') return V
def run(self, layers): """Impact plugin for hazard impact """ # Extract data H = get_hazard_layer(layers) # Value E = get_exposure_layer(layers) # Building locations # Interpolate hazard level to building locations H = H.interpolate(E, attribute_name='hazard_level') # Extract relevant numerical data coordinates = H.get_geometry() category = H.get_data() N = len(category) # List attributes to carry forward to result layer attributes = E.get_attribute_names() # Calculate building impact according to guidelines count2 = 0 count1 = 0 count0 = 0 building_impact = [] for i in range(N): # Get category value val = float(category[i]['hazard_level']) # Classify buildings according to value if val >= 2.0 / 3: affected = 2 count2 += 1 elif 1.0 / 3 <= val < 2.0 / 3: affected = 1 count1 += 1 else: affected = 0 count0 += 1 # Collect depth and calculated damage result_dict = {self.target_field: affected, 'CATEGORY': val} # Record result for this feature building_impact.append(result_dict) # Create report #FIXME: makes the output format the same as all other results impact_summary = ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % (_('Category'), _('Affected'), _('Low'), count0, _('Medium'), count1, _('High'), count2)) # Create style style_classes = [dict(label=_('Low'), min=0, max=0, colour='#1EFC7C', transparency=0, size=1), dict(label=_('Medium'), min=1, max=1, colour='#FFA500', transparency=0, size=1), dict(label=_('High'), min=2, max=2, colour='#F31A1C', transparency=0, size=1)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return name = 'Buildings Affected' V = Vector(data=building_impact, projection=E.get_projection(), geometry=coordinates, keywords={'impact_summary': impact_summary}, geometry_type=H.geometry_type, name=name, style_info=style_info) return V
def run(self, layers): """Risk plugin for tsunami population """ # Extract data H = get_hazard_layer(layers) # Depth R = get_exposure_layer(layers) # Building locations # Make the delta 10 times the size of the resolution. delta = abs(H.get_geotransform()[1]) * 10 min_value, max_value = H.get_extrema() E = convert_line_to_points(R, delta) # Interpolate hazard level to building locations H = H.interpolate(E) # Extract relevant numerical data coordinates = E.get_geometry() depth = H.get_data() N = len(depth) # List attributes to carry forward to result layer attributes = E.get_attribute_names() #print attributes #print 'Number of population points', N # Calculate population impact road_impact = [] num_classes = 10 classes = range(num_classes) difference = (max_value - min_value) / num_classes for i in range(N): dep = float(depth[i].values()[0]) affected = classes[0] for level in classes: normalized_depth = dep - min_value level_value = level * difference if normalized_depth > level_value: affected = level # Collect depth and calculated damage result_dict = {'AFFECTED': affected, 'DEPTH': dep} # Carry all original attributes forward for key in attributes: result_dict[key] = E.get_data(key, i) # Record result for this feature road_impact.append(result_dict) # Create report impact_summary = ('') # Create vector layer and return V = Vector(data=road_impact, projection=E.get_projection(), geometry=coordinates, name='Estimated roads affected', keywords={'impact_summary': impact_summary}) return V
def run(self, layers): """Risk plugin for tsunami population """ # Extract data H = get_hazard_layer(layers) # Depth E = get_exposure_layer(layers) # Building locations # Interpolate hazard level to building locations Hi = H.interpolate(E, attribute_name='depth') # Extract relevant numerical data coordinates = Hi.get_geometry() depth = Hi.get_data() N = len(depth) # List attributes to carry forward to result layer attributes = E.get_attribute_names() # Calculate building impact according to guidelines count3 = 0 count1 = 0 count0 = 0 population_impact = [] for i in range(N): if H.is_raster: # Get depth dep = float(depth[i]['depth']) # Classify buildings according to depth if dep >= 3: affected = 3 # FIXME: Colour upper bound is 100 but count3 += 1 # does not catch affected == 100 elif 1 <= dep < 3: affected = 2 count1 += 1 else: affected = 1 count0 += 1 elif H.is_vector: dep = 0 # Just put something here cat = depth[i]['Affected'] if cat is True: affected = 3 count3 += 1 else: affected = 1 count0 += 1 # Collect depth and calculated damage result_dict = {self.target_field: affected, 'DEPTH': dep} # Carry all original attributes forward # FIXME: This should be done in interpolation. Check. #for key in attributes: # result_dict[key] = E.get_data(key, i) # Record result for this feature population_impact.append(result_dict) # Create report Hname = H.get_name() Ename = E.get_name() if H.is_raster: impact_summary = ('<b>In case of "%s" the estimated impact to ' '"%s" ' 'is:</b><br><br><p>' % (Hname, Ename)) impact_summary += ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></tr>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % (_('Impact'), _('Number of buildings'), _('Low'), count0, _('Medium'), count1, _('High'), count3)) else: impact_summary = ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></tr>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % ('Terdampak oleh tsunami', 'Jumlah gedung', 'Terdampak', count3, 'Tidak terdampak', count0, 'Semua', N)) impact_summary += '<br>' # Blank separation row impact_summary += '<b>' + _('Assumption') + ':</b><br>' impact_summary += ('Levels of impact are defined by BNPB\'s ' '<i>Pengkajian Risiko Bencana</i>') impact_summary += ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></tr>' ' <tr></tr>' ' <tr><td>%s:</td><td>%s:</td></tr>' ' <tr><td>%s:</td><td>%s:</td></tr>' ' <tr><td>%s:</td><td>%s:</td></tr>' '</table>' % (_('Impact'), _('Tsunami height'), _('Low'), '<1 m', _('Medium'), '1-3 m', _('High'), '>3 m')) # Create style style_classes = [dict(label='< 1 m', min=0, max=1, colour='#1EFC7C', transparency=0, size=1), dict(label='1 - 3 m', min=1, max=2, colour='#FFA500', transparency=0, size=1), dict(label='> 3 m', min=2, max=4, colour='#F31A1C', transparency=0, size=1)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return if Hi.is_line_data: name = 'Roads flooded' elif Hi.is_point_data: name = 'Buildings flooded' V = Vector(data=population_impact, projection=E.get_projection(), geometry=coordinates, keywords={'impact_summary': impact_summary}, geometry_type=Hi.geometry_type, name=name, style_info=style_info) return V
def run(self, layers): """Risk plugin for tsunami population """ # Extract data H = get_hazard_layer(layers) # Depth E = get_exposure_layer(layers) # Building locations # Interpolate hazard level to building locations Hi = H.interpolate(E) # Extract relevant numerical data coordinates = E.get_geometry() depth = Hi.get_data() N = len(depth) # List attributes to carry forward to result layer attributes = E.get_attribute_names() # Calculate building impact according to guidelines count3 = 0 count1 = 0 count0 = 0 population_impact = [] for i in range(N): if H.is_raster: # Get depth dep = float(depth[i].values()[0]) # Classify buildings according to depth if dep >= 3: affected = 3 # FIXME: Colour upper bound is 100 but count3 += 1 # does not catch affected == 100 elif 1 <= dep < 3: affected = 2 count1 += 1 else: affected = 1 count0 += 1 elif H.is_vector: dep = 0 # Just put something here cat = depth[i]['Affected'] if cat is True: affected = 3 count3 += 1 else: affected = 1 count0 += 1 # Collect depth and calculated damage result_dict = {self.target_field: affected, 'DEPTH': dep} # Carry all original attributes forward for key in attributes: result_dict[key] = E.get_data(key, i) # Record result for this feature population_impact.append(result_dict) # Create report if H.is_raster: caption = ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % ('ketinggian tsunami', 'Jumlah gedung', '< 1 m', count0, '1 - 3 m', count1, '> 3 m', count3)) else: caption = ('<table border="0" width="320px">' ' <tr><th><b>%s</b></th><th><b>%s</b></th></th>' ' <tr></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' ' <tr><td>%s:</td><td>%i</td></tr>' '</table>' % ('Terdampak oleh tsunami', 'Jumlah gedung', 'Terdampak', count3, 'Tidak terdampak', count0, 'Semua', N)) # Create vector layer and return V = Vector(data=population_impact, projection=E.get_projection(), geometry=coordinates, name='Estimate of buildings affected', keywords={'caption': caption}) return V
def run(self, layers): """Risk plugin for Padang building survey """ # Extract data H = get_hazard_layer(layers) # Ground shaking E = get_exposure_layer(layers) # Building locations question = get_question(H.get_name(), E.get_name(), self) # Map from different kinds of datasets to Padang vulnerability classes datatype = E.get_keywords()['datatype'] vclass_tag = 'VCLASS' if datatype.lower() == 'osm': # Map from OSM attributes Emap = osm2padang(E) elif datatype.lower() == 'sigab': # Map from SIGAB attributes Emap = sigab2padang(E) else: Emap = E # Interpolate hazard level to building locations I = H.interpolate(Emap, attribute_name='MMI') # Extract relevant numerical data attributes = I.get_data() N = len(I) # Calculate building damage count_high = count_medium = count_low = count_none = 0 for i in range(N): mmi = float(attributes[i]['MMI']) building_type = Emap.get_data(vclass_tag, i) damage_params = damage_curves[building_type] beta = damage_params['beta'] median = damage_params['median'] percent_damage = lognormal_cdf(mmi, median=median, sigma=beta) * 100 # Add calculated impact to existing attributes attributes[i][self.target_field] = percent_damage # Calculate statistics if percent_damage < 10: count_none += 1 if 10 <= percent_damage < 33: count_low += 1 if 33 <= percent_damage < 66: count_medium += 1 if 66 <= percent_damage: count_high += 1 # Generate impact report table_body = [question, TableRow([_('Buildings'), _('Total')], header=True), TableRow([_('All'), N]), TableRow([_('No damage'), count_none]), TableRow([_('Low damage'), count_low]), TableRow([_('Medium damage'), count_medium]), TableRow([_('High damage'), count_high])] table_body.append(TableRow(_('Notes:'), header=True)) table_body.append(_('Levels of impact are defined by post 2009 ' 'Padang earthquake survey conducted by Geoscience ' 'Australia and Institute of Teknologi Bandung.')) table_body.append(_('Unreinforced masonry is assumed where no ' 'structural information is available.')) impact_summary = Table(table_body).toNewlineFreeString() impact_table = impact_summary map_title = _('Earthquake damage to buildings') # Create style style_classes = [dict(label=_('No damage'), min=0, max=10, colour='#00ff00', transparency=1), dict(label=_('Low damage'), min=10, max=33, colour='#ffff00', transparency=1), dict(label=_('Medium damage'), min=33, max=66, colour='#ffaa00', transparency=1), dict(label=_('High damage'), min=66, max=100, colour='#ff0000', transparency=1)] style_info = dict(target_field=self.target_field, style_classes=style_classes) # Create vector layer and return V = Vector(data=attributes, projection=E.get_projection(), geometry=E.get_geometry(), name='Estimated pct damage', keywords={'impact_summary': impact_summary, 'impact_table': impact_table, 'map_title': map_title}, style_info=style_info) return V