def building_damage_analysis_bulk_input(self, buildings): """Run analysis for multiple buildings. Args: buildings (list): Multiple buildings from input inventory set. Returns: dict: An ordered dictionary with building damage values. dict: An ordered dictionary with building data/metadata. """ # read static parameters from object self hazard_type = self.get_parameter("hazard_type") hazard_dataset_id = self.get_parameter("hazard_id") liq_geology_dataset_id = self.get_parameter("liq_geology_dataset_id") use_liquefaction = self.get_parameter("use_liquefaction") use_hazard_uncertainty = self.get_parameter("use_hazard_uncertainty") building_results = [] damage_results = [] fragility_sets_as = self.fragilitysvc.match_inventory( self.get_input_dataset("dfr3_mapping_set"), buildings, self.get_parameter("fragility_key_as")) fragility_sets_ds = self.fragilitysvc.match_inventory( self.get_input_dataset("dfr3_mapping_set"), buildings, self.get_parameter("fragility_key_ds")) values_payload_as = [] values_payload_ds = [] values_payload_liq = [] mapped_buildings = [] unmapped_buildings = [] for building in buildings: if building["id"] in fragility_sets_as and building[ "id"] in fragility_sets_ds: fragility_set_as = fragility_sets_as[building["id"]] fragility_set_ds = fragility_sets_ds[building["id"]] location = GeoUtil.get_location(building) loc = str(location.y) + "," + str(location.x) # Acceleration-Sensitive demands_as = AnalysisUtil.get_hazard_demand_types( building, fragility_set_as, hazard_type) units_as = fragility_set_as.demand_units value_as = { "demands": demands_as, "units": units_as, "loc": loc } values_payload_as.append(value_as) # Drift-Sensitive demands_ds = AnalysisUtil.get_hazard_demand_types( building, fragility_set_ds, hazard_type) units_ds = fragility_set_ds.demand_units value_ds = { "demands": demands_ds, "units": units_ds, "loc": loc } values_payload_ds.append(value_ds) # liquefaction if use_liquefaction: value_liq = { "demands": ["pgd"], # implied... "units": ["in"], "loc": loc } values_payload_liq.append(value_liq) mapped_buildings.append(building) else: unmapped_buildings.append(building) del buildings # get hazard values and liquefaction if hazard_type == 'earthquake': hazard_resp_as = self.hazardsvc.post_earthquake_hazard_values( hazard_dataset_id, values_payload_as) hazard_resp_ds = self.hazardsvc.post_earthquake_hazard_values( hazard_dataset_id, values_payload_ds) # adjust dmg probability for liquefaction if use_liquefaction: if liq_geology_dataset_id is not None: liquefaction_resp = self.hazardsvc.post_liquefaction_values( hazard_dataset_id, liq_geology_dataset_id, values_payload_liq) else: raise ValueError( 'Hazard does not support liquefaction! Check to make sure you defined the ' 'liquefaction portion of your scenario earthquake.') else: raise ValueError( "The provided hazard type is not supported yet by this analysis" ) # calculate LS and DS for i, building in enumerate(mapped_buildings): dmg_probability_as = {"LS_0": None, "LS_1": None, "LS_2": None} dmg_interval_as = { "DS_0": None, "DS_1": None, "DS_2": None, "DS_3": None } dmg_probability_ds = {"LS_0": None, "LS_1": None, "LS_2": None} dmg_interval_ds = { "DS_0": None, "DS_1": None, "DS_2": None, "DS_3": None } fragility_set_as = fragility_sets_as[building["id"]] fragility_set_ds = fragility_sets_ds[building["id"]] # TODO this value needs to come from the hazard service # adjust dmg probability for hazard uncertainty if use_hazard_uncertainty: raise ValueError('Uncertainty has not yet been implemented!') ############### # AS if isinstance(fragility_set_as.fragility_curves[0], DFR3Curve): hazard_vals_as = AnalysisUtil.update_precision_of_lists( hazard_resp_as[i]["hazardValues"]) demand_types_as = hazard_resp_as[i]["demands"] demand_units_as = hazard_resp_as[i]["units"] hval_dict_as = dict() for j, d in enumerate(fragility_set_as.demand_types): hval_dict_as[d] = hazard_vals_as[j] if not AnalysisUtil.do_hazard_values_have_errors( hazard_resp_as[i]["hazardValues"]): building_args = fragility_set_as.construct_expression_args_from_inventory( building) dmg_probability_as = fragility_set_as. \ calculate_limit_state(hval_dict_as, inventory_type="building", **building_args) # adjust dmg probability for liquefaction if use_liquefaction: if liq_geology_dataset_id is not None: liquefaction_dmg = AnalysisUtil.update_precision_of_lists( liquefaction_resp[i]["groundFailureProb"]) dmg_probability_as = AnalysisUtil.update_precision_of_dicts( NonStructBuildingUtil. adjust_damage_for_liquefaction( dmg_probability_as, liquefaction_dmg)) dmg_interval_as = fragility_set_ds.calculate_damage_interval( dmg_probability_as, hazard_type=hazard_type, inventory_type="building") else: raise ValueError( "One of the fragilities is in deprecated format. This should not happen. If you are " "seeing this please report the issue.") ############### # DS if isinstance(fragility_set_ds.fragility_curves[0], DFR3Curve): hazard_vals_ds = AnalysisUtil.update_precision_of_lists( hazard_resp_ds[i]["hazardValues"]) demand_types_ds = hazard_resp_ds[i]["demands"] demand_units_ds = hazard_resp_ds[i]["units"] hval_dict_ds = dict() for j, d in enumerate(fragility_set_ds.demand_types): hval_dict_ds[d] = hazard_vals_ds[j] if not AnalysisUtil.do_hazard_values_have_errors( hazard_resp_ds[i]["hazardValues"]): building_args = fragility_set_ds.construct_expression_args_from_inventory( building) dmg_probability_ds = fragility_set_ds. \ calculate_limit_state(hval_dict_ds, inventory_type="building", **building_args) # adjust dmg probability for liquefaction if use_liquefaction: if liq_geology_dataset_id is not None: liquefaction_dmg = AnalysisUtil.update_precision_of_lists( liquefaction_resp[i]["groundFailureProb"]) dmg_probability_ds = AnalysisUtil.update_precision_of_dicts( NonStructBuildingUtil. adjust_damage_for_liquefaction( dmg_probability_ds, liquefaction_dmg)) dmg_interval_ds = fragility_set_ds.calculate_damage_interval( dmg_probability_ds, hazard_type=hazard_type, inventory_type="building") else: raise ValueError( "One of the fragilities is in deprecated format. This should not happen. If you are " "seeing this please report the issue.") # put results in dictionary # AS denotes acceleration-sensitive fragility assigned to the building. # DS denotes drift-sensitive fragility assigned to the building. building_result = dict() building_result['guid'] = building['properties']['guid'] building_result['AS_LS_0'] = dmg_probability_as['LS_0'] building_result['AS_LS_1'] = dmg_probability_as['LS_1'] building_result['AS_LS_2'] = dmg_probability_as['LS_2'] building_result['AS_DS_0'] = dmg_interval_as['DS_0'] building_result['AS_DS_1'] = dmg_interval_as['DS_1'] building_result['AS_DS_2'] = dmg_interval_as['DS_2'] building_result['AS_DS_3'] = dmg_interval_as['DS_3'] building_result['DS_LS_0'] = dmg_probability_ds['LS_0'] building_result['DS_LS_1'] = dmg_probability_ds['LS_1'] building_result['DS_LS_2'] = dmg_probability_ds['LS_2'] building_result['DS_DS_0'] = dmg_interval_ds['DS_0'] building_result['DS_DS_1'] = dmg_interval_ds['DS_1'] building_result['DS_DS_2'] = dmg_interval_ds['DS_2'] building_result['DS_DS_3'] = dmg_interval_ds['DS_3'] building_result[ 'hazard_exposure_as'] = AnalysisUtil.get_exposure_from_hazard_values( hazard_vals_as, hazard_type) building_result[ 'hazard_exposure_ds'] = AnalysisUtil.get_exposure_from_hazard_values( hazard_vals_ds, hazard_type) # put damage results in dictionary damage_result = dict() damage_result['guid'] = building['properties']['guid'] damage_result['fragility_id_as'] = fragility_set_as.id damage_result['demandtypes_as'] = demand_types_as damage_result['demandunits_as'] = demand_units_as damage_result['fragility_id_ds'] = fragility_set_ds.id damage_result['demandtypes_ds'] = demand_types_ds damage_result['demandunits_ds'] = demand_units_ds damage_result['hazardtype'] = hazard_type damage_result['hazardvals_as'] = hazard_vals_as damage_result['hazardvals_ds'] = hazard_vals_ds building_results.append(building_result) damage_results.append(damage_result) for building in unmapped_buildings: building_result = dict() building_result['guid'] = building['properties']['guid'] damage_result = dict() damage_result['guid'] = building['properties']['guid'] damage_result['fragility_id_as'] = None damage_result['demandtypes_as'] = None damage_result['demandunits_as'] = None damage_result['fragility_id_ds'] = None damage_result['demandtypes_ds'] = None damage_result['demandunits_ds'] = None damage_result['hazardtype'] = None damage_result['hazardvals_as'] = None damage_result['hazardvals_ds'] = None building_results.append(building_result) damage_results.append(damage_result) return building_results, damage_results
def building_damage_analysis_bulk_input(self, buildings, retrofit_strategy, hazard_type, hazard_dataset_id): """Run analysis for multiple buildings. Args: buildings (list): Multiple buildings from input inventory set. retrofit_strategy (list): building guid and its retrofit level 0, 1, 2, etc. This is Optional hazard_type (str): Hazard type, either earthquake, tornado, or tsunami. hazard_dataset_id (str): An id of the hazard exposure. Returns: list: A list of ordered dictionaries with building damage values and other data/metadata. """ fragility_key = self.get_parameter("fragility_key") fragility_sets = self.fragilitysvc.match_inventory(self.get_input_dataset("dfr3_mapping_set"), buildings, fragility_key, retrofit_strategy) values_payload = [] unmapped_buildings = [] mapped_buildings = [] for b in buildings: bldg_id = b["id"] if bldg_id in fragility_sets: location = GeoUtil.get_location(b) loc = str(location.y) + "," + str(location.x) demands = AnalysisUtil.get_hazard_demand_types(b, fragility_sets[bldg_id], hazard_type) units = fragility_sets[bldg_id].demand_units value = { "demands": demands, "units": units, "loc": loc } values_payload.append(value) mapped_buildings.append(b) else: unmapped_buildings.append(b) # not needed anymore as they are already split into mapped and unmapped del buildings if hazard_type == 'earthquake': hazard_vals = self.hazardsvc.post_earthquake_hazard_values(hazard_dataset_id, values_payload) elif hazard_type == 'tornado': hazard_vals = self.hazardsvc.post_tornado_hazard_values(hazard_dataset_id, values_payload, self.get_parameter('seed')) elif hazard_type == 'tsunami': hazard_vals = self.hazardsvc.post_tsunami_hazard_values(hazard_dataset_id, values_payload) elif hazard_type == 'hurricane': hazard_vals = self.hazardsvc.post_hurricane_hazard_values(hazard_dataset_id, values_payload) elif hazard_type == 'flood': hazard_vals = self.hazardsvc.post_flood_hazard_values(hazard_dataset_id, values_payload) else: raise ValueError("The provided hazard type is not supported yet by this analysis") ds_results = [] damage_results = [] i = 0 for b in mapped_buildings: ds_result = dict() damage_result = dict() dmg_probability = dict() dmg_interval = dict() b_id = b["id"] selected_fragility_set = fragility_sets[b_id] # TODO: Once all fragilities are migrated to new format, we can remove this condition if isinstance(selected_fragility_set.fragility_curves[0], DFR3Curve): # Supports multiple demand types in same fragility b_haz_vals = AnalysisUtil.update_precision_of_lists(hazard_vals[i]["hazardValues"]) b_demands = hazard_vals[i]["demands"] b_units = hazard_vals[i]["units"] hval_dict = dict() j = 0 # To calculate damage, use demand type name from fragility that will be used in the expression, instead # of using what the hazard service returns. There could be a difference "SA" in DFR3 vs "1.07 SA" # from hazard for d in selected_fragility_set.demand_types: hval_dict[d] = b_haz_vals[j] j += 1 if not AnalysisUtil.do_hazard_values_have_errors(hazard_vals[i]["hazardValues"]): building_args = selected_fragility_set.construct_expression_args_from_inventory(b) building_period = selected_fragility_set.fragility_curves[0].get_building_period( selected_fragility_set.curve_parameters, **building_args) dmg_probability = selected_fragility_set.calculate_limit_state( hval_dict, **building_args, period=building_period) dmg_interval = selected_fragility_set.calculate_damage_interval( dmg_probability, hazard_type=hazard_type, inventory_type="building") else: raise ValueError("One of the fragilities is in deprecated format. This should not happen. If you are " "seeing this please report the issue.") ds_result['guid'] = b['properties']['guid'] damage_result['guid'] = b['properties']['guid'] ds_result.update(dmg_probability) ds_result.update(dmg_interval) ds_result['haz_expose'] = AnalysisUtil.get_exposure_from_hazard_values(b_haz_vals, hazard_type) damage_result['fragility_id'] = selected_fragility_set.id damage_result['demandtype'] = b_demands damage_result['demandunits'] = b_units damage_result['hazardval'] = b_haz_vals ds_results.append(ds_result) damage_results.append(damage_result) i += 1 for b in unmapped_buildings: ds_result = dict() damage_result = dict() ds_result['guid'] = b['properties']['guid'] damage_result['guid'] = b['properties']['guid'] damage_result['fragility_id'] = None damage_result['demandtype'] = None damage_result['demandunits'] = None damage_result['hazardval'] = None ds_results.append(ds_result) damage_results.append(damage_result) return ds_results, damage_results
def pipeline_damage_analysis_bulk_input(self, pipelines, hazard_type, hazard_dataset_id): """Run pipeline damage analysis for multiple pipelines. Args: pipelines (list): Multiple pipelines from pipeline dataset. hazard_type (str): Hazard type (earthquake or tsunami). hazard_dataset_id (str): An id of the hazard exposure. Returns: dict: An ordered dictionaries with pipeline damage values. dict: An ordered dictionaries with other pipeline data/metadata. """ # Get Fragility key fragility_key = self.get_parameter("fragility_key") if fragility_key is None: fragility_key = "Non-Retrofit inundationDepth Fragility ID Code" if hazard_type == 'tsunami' else "pgv" self.set_parameter("fragility_key", fragility_key) # get fragility set fragility_sets = self.fragilitysvc.match_inventory( self.get_input_dataset("dfr3_mapping_set"), pipelines, fragility_key) values_payload = [] unmapped_pipelines = [] mapped_pipelines = [] for pipeline in pipelines: # if find a match fragility for that pipeline if pipeline["id"] in fragility_sets.keys(): fragility_set = fragility_sets[pipeline["id"]] location = GeoUtil.get_location(pipeline) loc = str(location.y) + "," + str(location.x) demands = AnalysisUtil.get_hazard_demand_types( pipeline, fragility_set, hazard_type) units = fragility_sets[pipeline["id"]].demand_units value = {"demands": demands, "units": units, "loc": loc} values_payload.append(value) mapped_pipelines.append(pipeline) else: unmapped_pipelines.append(pipeline) # not needed anymore as they are already split into mapped and unmapped del pipelines if hazard_type == 'earthquake': hazard_vals = self.hazardsvc.post_earthquake_hazard_values( hazard_dataset_id, values_payload) elif hazard_type == 'tornado': raise ValueError( "The provided hazard type is not supported yet by this analysis" ) elif hazard_type == 'tsunami': hazard_vals = self.hazardsvc.post_tsunami_hazard_values( hazard_dataset_id, values_payload) elif hazard_type == 'hurricane': raise ValueError( "The provided hazard type is not supported yet by this analysis" ) elif hazard_type == 'flood': raise ValueError( "The provided hazard type is not supported yet by this analysis" ) else: raise ValueError( "The provided hazard type is not supported yet by this analysis" ) pipeline_results = [] damage_results = [] for i, pipeline in enumerate(mapped_pipelines): limit_states = dict() dmg_intervals = dict() pipeline_result = dict() fragility_set = fragility_sets[pipeline["id"]] # TODO: Once all fragilities are migrated to new format, we can remove this condition if isinstance(fragility_set.fragility_curves[0], DFR3Curve): # Supports multiple demand types in same fragility haz_vals = AnalysisUtil.update_precision_of_lists( hazard_vals[i]["hazardValues"]) demand_types = hazard_vals[i]["demands"] demand_units = hazard_vals[i]["units"] # construct hazard_value dictionary {"demand_type":"hazard_value", ...} hval_dict = dict() for j, d in enumerate(fragility_set.demand_types): hval_dict[d] = haz_vals[j] if not AnalysisUtil.do_hazard_values_have_errors( hazard_vals[i]["hazardValues"]): pipeline_args = fragility_set.construct_expression_args_from_inventory( pipeline) limit_states = fragility_set.calculate_limit_state( hval_dict, inventory_type="pipeline", **pipeline_args) dmg_intervals = fragility_set.calculate_damage_interval( limit_states, hazard_type=hazard_type, inventory_type="pipeline") else: raise ValueError( "One of the fragilities is in deprecated format. This should not happen. If you are " "seeing this please report the issue.") pipeline_result['guid'] = pipeline['properties']['guid'] pipeline_result.update(limit_states) pipeline_result.update(dmg_intervals) pipeline_result[ 'haz_expose'] = AnalysisUtil.get_exposure_from_hazard_values( haz_vals, hazard_type) damage_result = dict() damage_result['guid'] = pipeline['properties']['guid'] damage_result['fragility_id'] = fragility_set.id damage_result['demandtypes'] = demand_types damage_result['demandunits'] = demand_units damage_result['hazardtype'] = hazard_type damage_result['hazardval'] = haz_vals pipeline_results.append(pipeline_result) damage_results.append(damage_result) # for pipeline does not have matching fragility curves, default to None for pipeline in unmapped_pipelines: pipeline_result = dict() damage_result = dict() pipeline_result['guid'] = pipeline['properties']['guid'] damage_result['guid'] = pipeline['properties']['guid'] damage_result['fragility_id'] = None damage_result['demandtypes'] = None damage_result['demandunits'] = None damage_result['hazardtype'] = None damage_result['hazardvals'] = None pipeline_results.append(pipeline_result) damage_results.append(damage_result) return pipeline_results, damage_results