Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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