コード例 #1
0
ファイル: impact_function.py プロジェクト: neogis-de/inasafe
    def run(self, layers=None):
        """Classified hazard impact to buildings (e.g. from Open Street Map).

         :param layers: List of layers expected to contain.
                * hazard: Classified Hazard layer
                * exposure: Vector layer of structure data on
                the same grid as hazard
        """
        self.validate()
        self.prepare(layers)

        # The 3 classes
        low_t = self.parameters['low_hazard_class']
        medium_t = self.parameters['medium_hazard_class']
        high_t = self.parameters['high_hazard_class']

        # Extract data
        hazard = self.hazard  # Classified Hazard
        exposure = self.exposure  # Building locations

        # Determine attribute name for hazard levels
        if hazard.is_raster:
            hazard_attribute = 'level'
        else:
            hazard_attribute = None

        interpolated_result = assign_hazard_values_to_exposure_data(
            hazard, exposure, attribute_name=hazard_attribute, mode='constant')

        # Extract relevant exposure data
        attribute_names = interpolated_result.get_attribute_names()
        attributes = interpolated_result.get_data()

        buildings_total = len(interpolated_result)
        # Calculate building impact
        self.buildings = {}
        self.affected_buildings = OrderedDict([(tr('High Hazard Class'), {}),
                                               (tr('Medium Hazard Class'), {}),
                                               (tr('Low Hazard Class'), {})])
        for i in range(buildings_total):
            usage = get_osm_building_usage(attribute_names, attributes[i])
            if usage is None or usage == 0:
                usage = 'unknown'

            if usage not in self.buildings:
                self.buildings[usage] = 0
                for category in self.affected_buildings.keys():
                    self.affected_buildings[category][usage] = OrderedDict([
                        (tr('Buildings Affected'), 0)
                    ])

            # Count all buildings by type
            self.buildings[usage] += 1
            attributes[i][self.target_field] = 0
            attributes[i][self.affected_field] = 0
            level = float(attributes[i]['level'])
            level = float(numpy_round(level))
            if level == high_t:
                impact_level = tr('High Hazard Class')
            elif level == medium_t:
                impact_level = tr('Medium Hazard Class')
            elif level == low_t:
                impact_level = tr('Low Hazard Class')
            else:
                continue

            # Add calculated impact to existing attributes
            attributes[i][self.target_field] = {
                tr('High Hazard Class'): 3,
                tr('Medium Hazard Class'): 2,
                tr('Low Hazard Class'): 1
            }[impact_level]
            attributes[i][self.affected_field] = 1
            # Count affected buildings by type
            self.affected_buildings[impact_level][usage][tr(
                'Buildings Affected')] += 1

        # Consolidate the small building usage groups < 25 to other
        self._consolidate_to_other()

        # Create style
        style_classes = [
            dict(label=tr('High'),
                 value=3,
                 colour='#F31A1C',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Medium'),
                 value=2,
                 colour='#F4A442',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Low'),
                 value=1,
                 colour='#EBF442',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Not Affected'),
                 value=None,
                 colour='#1EFC7C',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2)
        ]
        style_info = dict(target_field=self.target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')

        impact_table = impact_summary = self.generate_html_report()
        # For printing map purpose
        map_title = tr('Buildings affected')
        legend_units = tr('(Low, Medium, High)')
        legend_title = tr('Structure inundated status')

        # Create vector layer and return
        vector_layer = Vector(data=attributes,
                              projection=exposure.get_projection(),
                              geometry=exposure.get_geometry(),
                              name=tr('Estimated buildings affected'),
                              keywords={
                                  'impact_summary':
                                  impact_summary,
                                  'impact_table':
                                  impact_table,
                                  'target_field':
                                  self.affected_field,
                                  'map_title':
                                  map_title,
                                  'legend_units':
                                  legend_units,
                                  'legend_title':
                                  legend_title,
                                  'buildings_total':
                                  buildings_total,
                                  'buildings_affected':
                                  self.total_affected_buildings
                              },
                              style_info=style_info)
        self._impact = vector_layer
        return vector_layer
コード例 #2
0
ファイル: impact_function.py プロジェクト: Mloweedgar/inasafe
    def run(self):
        """Classified hazard impact to buildings (e.g. from Open Street Map).
        """
        self.validate()
        self.prepare()

        # Value from layer's keywords
        # Try to get the value from keyword, if not exist, it will not fail,
        # but use the old get_osm_building_usage
        try:
            structure_class_field = self.exposure.keyword(
                'structure_class_field')
        except KeywordNotFoundError:
            structure_class_field = None

        # The 3 classes
        categorical_hazards = self.parameters['Categorical hazards'].value
        low_t = categorical_hazards[0].value
        medium_t = categorical_hazards[1].value
        high_t = categorical_hazards[2].value

        # Determine attribute name for hazard levels
        if self.hazard.layer.is_raster:
            hazard_attribute = 'level'
        else:
            hazard_attribute = None

        interpolated_result = assign_hazard_values_to_exposure_data(
            self.hazard.layer,
            self.exposure.layer,
            attribute_name=hazard_attribute,
            mode='constant')

        # Extract relevant exposure data
        attribute_names = interpolated_result.get_attribute_names()
        attributes = interpolated_result.get_data()

        buildings_total = len(interpolated_result)
        # Calculate building impact
        self.buildings = {}
        self.affected_buildings = OrderedDict([
            (tr('High Hazard Class'), {}),
            (tr('Medium Hazard Class'), {}),
            (tr('Low Hazard Class'), {})
        ])
        for i in range(buildings_total):

            if (structure_class_field and
                    structure_class_field in attribute_names):
                usage = attributes[i][structure_class_field]
            else:
                usage = get_osm_building_usage(attribute_names, attributes[i])

            if usage is None or usage == 0:
                usage = 'unknown'

            if usage not in self.buildings:
                self.buildings[usage] = 0
                for category in self.affected_buildings.keys():
                    self.affected_buildings[category][usage] = OrderedDict([
                        (tr('Buildings Affected'), 0)])

            # Count all buildings by type
            self.buildings[usage] += 1
            attributes[i][self.target_field] = 0
            attributes[i][self.affected_field] = 0
            level = float(attributes[i]['level'])
            level = float(numpy_round(level))
            if level == high_t:
                impact_level = tr('High Hazard Class')
            elif level == medium_t:
                impact_level = tr('Medium Hazard Class')
            elif level == low_t:
                impact_level = tr('Low Hazard Class')
            else:
                continue

            # Add calculated impact to existing attributes
            attributes[i][self.target_field] = {
                tr('High Hazard Class'): 3,
                tr('Medium Hazard Class'): 2,
                tr('Low Hazard Class'): 1
            }[impact_level]
            attributes[i][self.affected_field] = 1
            # Count affected buildings by type
            self.affected_buildings[impact_level][usage][
                tr('Buildings Affected')] += 1

        # Consolidate the small building usage groups < 25 to other
        self._consolidate_to_other()

        # Create style
        style_classes = [dict(label=tr('High'),
                              value=3,
                              colour='#F31A1C',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Medium'),
                              value=2,
                              colour='#F4A442',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Low'),
                              value=1,
                              colour='#EBF442',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Not Affected'),
                              value=None,
                              colour='#1EFC7C',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2)]
        style_info = dict(target_field=self.target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')

        impact_table = impact_summary = self.html_report()

        # For printing map purpose
        map_title = tr('Buildings affected')
        legend_title = tr('Structure inundated status')
        legend_units = tr('(Low, Medium, High)')

        # Create vector layer and return
        vector_layer = Vector(
            data=attributes,
            projection=self.exposure.layer.get_projection(),
            geometry=self.exposure.layer.get_geometry(),
            name=tr('Estimated buildings affected'),
            keywords={
                'impact_summary': impact_summary,
                'impact_table': impact_table,
                'target_field': self.affected_field,
                'map_title': map_title,
                'legend_units': legend_units,
                'legend_title': legend_title,
                'buildings_total': buildings_total,
                'buildings_affected': self.total_affected_buildings},
            style_info=style_info)
        self._impact = vector_layer
        return vector_layer
コード例 #3
0
    def run(self):
        """Classified hazard impact to buildings (e.g. from Open Street Map).
        """
        self.validate()
        self.prepare()

        self.provenance.append_step(
            'Calculating Step', 'Impact function is calculating the impact.')

        # Value from layer's keywords
        # Try to get the value from keyword, if not exist, it will not fail,
        # but use the old get_osm_building_usage
        try:
            structure_class_field = self.exposure.keyword(
                'structure_class_field')
        except KeywordNotFoundError:
            structure_class_field = None

        # The 3 classes
        categorical_hazards = self.parameters['Categorical hazards'].value
        low_t = categorical_hazards[0].value
        medium_t = categorical_hazards[1].value
        high_t = categorical_hazards[2].value

        # Determine attribute name for hazard levels
        if self.hazard.layer.is_raster:
            hazard_attribute = 'level'
        else:
            hazard_attribute = None

        interpolated_result = assign_hazard_values_to_exposure_data(
            self.hazard.layer,
            self.exposure.layer,
            attribute_name=hazard_attribute,
            mode='constant')

        # Extract relevant exposure data
        attribute_names = interpolated_result.get_attribute_names()
        attributes = interpolated_result.get_data()

        buildings_total = len(interpolated_result)
        # Calculate building impact
        self.buildings = {}
        self.affected_buildings = OrderedDict([(tr('High Hazard Class'), {}),
                                               (tr('Medium Hazard Class'), {}),
                                               (tr('Low Hazard Class'), {})])
        for i in range(buildings_total):

            if (structure_class_field
                    and structure_class_field in attribute_names):
                usage = attributes[i][structure_class_field]
            else:
                usage = get_osm_building_usage(attribute_names, attributes[i])

            if usage is None or usage == 0:
                usage = 'unknown'

            if usage not in self.buildings:
                self.buildings[usage] = 0
                for category in self.affected_buildings.keys():
                    self.affected_buildings[category][usage] = OrderedDict([
                        (tr('Buildings Affected'), 0)
                    ])

            # Count all buildings by type
            self.buildings[usage] += 1
            attributes[i][self.target_field] = 0
            attributes[i][self.affected_field] = 0
            level = float(attributes[i]['level'])
            level = float(numpy_round(level))
            if level == high_t:
                impact_level = tr('High Hazard Class')
            elif level == medium_t:
                impact_level = tr('Medium Hazard Class')
            elif level == low_t:
                impact_level = tr('Low Hazard Class')
            else:
                continue

            # Add calculated impact to existing attributes
            attributes[i][self.target_field] = {
                tr('High Hazard Class'): 3,
                tr('Medium Hazard Class'): 2,
                tr('Low Hazard Class'): 1
            }[impact_level]
            attributes[i][self.affected_field] = 1
            # Count affected buildings by type
            self.affected_buildings[impact_level][usage][tr(
                'Buildings Affected')] += 1

        # Consolidate the small building usage groups < 25 to other
        # Building threshold #2468
        postprocessors = self.parameters['postprocessors']
        building_postprocessors = postprocessors['BuildingType'][0]
        self.building_report_threshold = building_postprocessors.value[0].value
        self._consolidate_to_other()

        # Create style
        style_classes = [
            dict(label=tr('High'),
                 value=3,
                 colour='#F31A1C',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Medium'),
                 value=2,
                 colour='#F4A442',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Low'),
                 value=1,
                 colour='#EBF442',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Not Affected'),
                 value=None,
                 colour='#1EFC7C',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2)
        ]
        style_info = dict(target_field=self.target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')

        impact_table = impact_summary = self.html_report()

        # For printing map purpose
        map_title = tr('Buildings affected')
        legend_title = tr('Structure inundated status')
        legend_units = tr('(Low, Medium, High)')

        extra_keywords = {
            'impact_summary': impact_summary,
            'impact_table': impact_table,
            'target_field': self.affected_field,
            'map_title': map_title,
            'legend_units': legend_units,
            'legend_title': legend_title,
            'buildings_total': buildings_total,
            'buildings_affected': self.total_affected_buildings
        }

        self.set_if_provenance()

        impact_layer_keywords = self.generate_impact_keywords(extra_keywords)

        # Create vector layer and return
        vector_layer = Vector(data=attributes,
                              projection=self.exposure.layer.get_projection(),
                              geometry=self.exposure.layer.get_geometry(),
                              name=tr('Estimated buildings affected'),
                              keywords=impact_layer_keywords,
                              style_info=style_info)
        self._impact = vector_layer
        return vector_layer
コード例 #4
0
    def run(self, layers):
        """Classified hazard impact to buildings (e.g. from Open Street Map).

         :param layers: List of layers expected to contain.
                * hazard: Classified Hazard layer
                * exposure: Vector layer of structure data on
                the same grid as hazard
        """

        # The 3 classes
        low_t = self.parameters['low_hazard_class']
        medium_t = self.parameters['medium_hazard_class']
        high_t = self.parameters['high_hazard_class']

        # Extract data
        hazard = get_hazard_layer(layers)  # Classified Hazard
        exposure = get_exposure_layer(layers)  # Building locations

        question = get_question(hazard.get_name(), exposure.get_name(), self)

        # Determine attribute name for hazard levels
        if hazard.is_raster:
            hazard_attribute = 'level'
        else:
            hazard_attribute = None

        interpolated_result = assign_hazard_values_to_exposure_data(
            hazard, exposure, attribute_name=hazard_attribute, mode='constant')

        # Extract relevant exposure data
        attribute_names = interpolated_result.get_attribute_names()
        attributes = interpolated_result.get_data()

        N = len(interpolated_result)
        # Calculate building impact
        count = 0
        count1 = 0
        count2 = 0
        count3 = 0
        buildings = {}
        affected_buildings = {}
        for i in range(N):
            # Get class value
            val = float(attributes[i]['level'])
            # FIXME it would be good if the affected were words not numbers
            # FIXME need to read hazard layer and see class or keyword
            val = float(numpy_round(val))
            if val == high_t:
                count3 += 1
            elif val == medium_t:
                count2 += 1
            elif val == low_t:
                count1 += 1
            else:
                count += 1

            # Count affected buildings by usage type if available
            if 'type' in attribute_names:
                usage = attributes[i]['type']
            elif 'TYPE' in attribute_names:
                usage = attributes[i]['TYPE']
            else:
                usage = None
            if 'amenity' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['amenity']
            if 'building_t' in attribute_names and (usage is None
                                                    or usage == 0):
                usage = attributes[i]['building_t']
            if 'office' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['office']
            if 'tourism' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['tourism']
            if 'leisure' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['leisure']
            if 'building' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['building']
                if usage == 'yes':
                    usage = 'building'

            if usage is not None and usage != 0:
                key = usage
            else:
                key = 'unknown'

            if key not in buildings:
                buildings[key] = 0
                affected_buildings[key] = 0

            # Count all buildings by type
            buildings[key] += 1
            if val is True:
                # Count affected buildings by type
                affected_buildings[key] += 1

            # Add calculated impact to existing attributes
            if val == high_t:
                attributes[i][self.target_field] = 3
                attributes[i][self.affected_field] = 1

            elif val == medium_t:
                attributes[i][self.target_field] = 2
                attributes[i][self.affected_field] = 1

            elif val == low_t:
                attributes[i][self.target_field] = 1
                attributes[i][self.affected_field] = 1

            else:
                attributes[i][self.target_field] = 0
                attributes[i][self.affected_field] = 0

        # Lump small entries and 'unknown' into 'other' category
        for usage in buildings.keys():
            val = buildings[usage]
            if val < 25 or usage == 'unknown':
                if 'other' not in buildings:
                    buildings['other'] = 0
                    affected_buildings['other'] = 0

                buildings['other'] += val
                affected_buildings['other'] += affected_buildings[usage]
                del buildings[usage]
                del affected_buildings[usage]

        # Generate impact summary
            table_body = [
                question,
                TableRow([tr('Hazard Level'),
                          tr('Number of Buildings')],
                         header=True),
                TableRow([tr('High Hazard Class'),
                          format_int(count3)]),
                TableRow([tr('Medium Hazard Class'),
                          format_int(count2)]),
                TableRow([tr('Low Hazard Class'),
                          format_int(count1)]),
                TableRow([
                    tr('Total Buildings Affected'),
                    format_int(count1 + count2 + count3)
                ],
                         header=True),
                TableRow([tr('Buildings Not Affected'),
                          format_int(count)],
                         header=True),
                TableRow(
                    [tr('All Buildings'), format_int(N)], header=True)
            ]

        school_closed = 0
        hospital_closed = 0
        # Generate break down by building usage type is available
        list_type_attribute = [
            'TYPE', 'type', 'amenity', 'building_t', 'office', 'tourism',
            'leisure', 'building'
        ]
        intersect_type = set(attribute_names) & set(list_type_attribute)
        if len(intersect_type) > 0:
            # Make list of building types
            building_list = []
            for usage in buildings:
                building_type = usage.replace('_', ' ')

                # Lookup internationalised value if available
                building_type = tr(building_type)
                building_list.append([
                    building_type.capitalize(),
                    format_int(affected_buildings[usage]),
                    format_int(buildings[usage])
                ])
                if building_type == 'school':
                    school_closed = affected_buildings[usage]
                if building_type == 'hospital':
                    hospital_closed = affected_buildings[usage]

            # Sort alphabetically
            building_list.sort()

            table_body.append(
                TableRow(tr('Breakdown by building type'), header=True))
            for row in building_list:
                s = TableRow(row)
                table_body.append(s)

        table_body.append(TableRow(tr('Action Checklist:'), header=True))
        table_body.append(
            TableRow(tr('Are the critical facilities still open?')))
        table_body.append(
            TableRow(
                tr('Which structures have warning capacity (eg. sirens, speakers, '
                   'etc.)?')))
        table_body.append(
            TableRow(tr('Which buildings will be evacuation centres?')))
        table_body.append(
            TableRow(tr('Where will we locate the operations centre?')))
        table_body.append(
            TableRow(
                tr('Where will we locate warehouse and/or distribution centres?'
                   )))

        if school_closed > 0:
            table_body.append(
                TableRow(
                    tr('Where will the students from the %s closed schools go to '
                       'study?') % format_int(school_closed)))

        if hospital_closed > 0:
            table_body.append(
                TableRow(
                    tr('Where will the patients from the %s closed hospitals go '
                       'for treatment and how will we transport them?') %
                    format_int(hospital_closed)))

        table_body.append(TableRow(tr('Notes'), header=True))
        table_body.append(
            tr('Map shows buildings affected in'
               ' low, medium and high hazard class areas.'))

        # Result
        impact_summary = Table(table_body).toNewlineFreeString()
        impact_table = impact_summary

        # Create style
        style_classes = [
            dict(label=tr('High'),
                 value=3,
                 colour='#F31A1C',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Medium'),
                 value=2,
                 colour='#F4A442',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Low'),
                 value=1,
                 colour='#EBF442',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Not Affected'),
                 value=None,
                 colour='#1EFC7C',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2)
        ]
        style_info = dict(target_field=self.target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')

        # For printing map purpose
        map_title = tr('Buildings affected')
        legend_units = tr('(Low, Medium, High)')
        legend_title = tr('Structure inundated status')

        # Create vector layer and return
        vector_layer = Vector(data=attributes,
                              projection=exposure.get_projection(),
                              geometry=exposure.get_geometry(),
                              name=tr('Estimated buildings affected'),
                              keywords={
                                  'impact_summary': impact_summary,
                                  'impact_table': impact_table,
                                  'target_field': self.affected_field,
                                  'map_title': map_title,
                                  'legend_units': legend_units,
                                  'legend_title': legend_title,
                                  'buildings_total': N,
                                  'buildings_affected':
                                  count1 + count2 + count3
                              },
                              style_info=style_info)
        return vector_layer
コード例 #5
0
    def run(self):
        """Classified hazard impact to buildings (e.g. from Open Street Map).
        """

        # Value from layer's keywords
        structure_class_field = self.exposure.keyword("structure_class_field")
        try:
            exposure_value_mapping = self.exposure.keyword("value_mapping")
        except KeywordNotFoundError:
            # Generic IF, the keyword might not be defined base.py
            exposure_value_mapping = {}
        self.hazard_class_mapping = self.hazard.keyword("value_map")

        keys = [x["key"] for x in generic_raster_hazard_classes["classes"]]
        names = [x["name"] for x in generic_raster_hazard_classes["classes"]]
        classes = OrderedDict()
        for i in range(len(keys)):
            classes[keys[i]] = names[i]

        # Determine attribute name for hazard class
        hazard_class_attribute = get_non_conflicting_attribute_name(
            "haz_class", [x.keys() for x in self.exposure.layer.data][0]
        )

        interpolated_result = assign_hazard_values_to_exposure_data(
            self.hazard.layer, self.exposure.layer, attribute_name=hazard_class_attribute, mode="constant"
        )

        # Extract relevant exposure data
        attributes = interpolated_result.get_data()

        # Number of building in the interpolated layer
        buildings_total = len(interpolated_result)

        # Inverse the order from low to high
        self.init_report_var(classes.values()[::-1])

        for i in range(buildings_total):
            # Get the usage of the building
            usage = attributes[i][structure_class_field]
            usage = main_type(usage, exposure_value_mapping)

            # Initialize value as Not affected
            attributes[i][self.target_field] = tr("Not affected")
            attributes[i][self.affected_field] = 0

            # Get the hazard level of the building
            level = float(attributes[i][hazard_class_attribute])
            level = float(numpy_round(level))

            # Find the class according the building's level
            for k, v in self.hazard_class_mapping.items():
                if level in v:
                    impact_class = classes[k]
                    # Set the impact level
                    attributes[i][self.target_field] = impact_class
                    # Set to affected
                    attributes[i][self.affected_field] = 1
                    break

            # Count affected buildings by type
            self.classify_feature(attributes[i][self.target_field], usage, bool(attributes[i][self.affected_field]))

        self.reorder_dictionaries()

        # Create style
        # Low, Medium and High are translated in the attribute table.
        # "Not affected" is not translated in the attribute table.
        style_classes = [
            dict(
                label=tr("Not Affected"),
                value="Not affected",
                colour="#1EFC7C",
                transparency=0,
                size=2,
                border_color="#969696",
                border_width=0.2,
            ),
            dict(
                label=tr("Low"),
                value=tr("Low hazard zone"),
                colour="#EBF442",
                transparency=0,
                size=2,
                border_color="#969696",
                border_width=0.2,
            ),
            dict(
                label=tr("Medium"),
                value=tr("Medium hazard zone"),
                colour="#F4A442",
                transparency=0,
                size=2,
                border_color="#969696",
                border_width=0.2,
            ),
            dict(
                label=tr("High"),
                value=tr("High hazard zone"),
                colour="#F31A1C",
                transparency=0,
                size=2,
                border_color="#969696",
                border_width=0.2,
            ),
        ]
        style_info = dict(target_field=self.target_field, style_classes=style_classes, style_type="categorizedSymbol")
        LOGGER.debug("target field : " + self.target_field)

        impact_data = self.generate_data()

        extra_keywords = {
            "target_field": self.affected_field,
            "map_title": self.map_title(),
            "legend_units": self.metadata().key("legend_units"),
            "legend_title": self.metadata().key("legend_title"),
            "buildings_total": buildings_total,
            "buildings_affected": self.total_affected_buildings,
        }

        impact_layer_keywords = self.generate_impact_keywords(extra_keywords)

        # Create impact layer and return
        impact_layer = Vector(
            data=attributes,
            projection=self.exposure.layer.get_projection(),
            geometry=self.exposure.layer.get_geometry(),
            name=self.map_title(),
            keywords=impact_layer_keywords,
            style_info=style_info,
        )

        impact_layer.impact_data = impact_data
        self._impact = impact_layer
        return impact_layer
コード例 #6
0
    def run(self, layers):
        """Classified hazard impact to buildings (e.g. from Open Street Map).

         :param layers: List of layers expected to contain.
                * hazard: Classified Hazard layer
                * exposure: Vector layer of structure data on
                the same grid as hazard
        """

        # The 3 classes
        low_t = self.parameters['low_hazard_class']
        medium_t = self.parameters['medium_hazard_class']
        high_t = self.parameters['high_hazard_class']

        # Extract data
        hazard = get_hazard_layer(layers)  # Classified Hazard
        exposure = get_exposure_layer(layers)  # Building locations

        question = get_question(hazard.get_name(), exposure.get_name(), self)

        # Determine attribute name for hazard levels
        if hazard.is_raster:
            hazard_attribute = 'level'
        else:
            hazard_attribute = None

        interpolated_result = assign_hazard_values_to_exposure_data(
            hazard,
            exposure,
            attribute_name=hazard_attribute,
            mode='constant')

        # Extract relevant exposure data
        attribute_names = interpolated_result.get_attribute_names()
        attributes = interpolated_result.get_data()

        N = len(interpolated_result)
        # Calculate building impact
        count = 0
        count1 = 0
        count2 = 0
        count3 = 0
        buildings = {}
        affected_buildings = {}
        for i in range(N):
            # Get class value
            val = float(attributes[i]['level'])
            # FIXME it would be good if the affected were words not numbers
            # FIXME need to read hazard layer and see class or keyword
            val = float(numpy_round(val))
            if val == high_t:
                count3 += 1
            elif val == medium_t:
                count2 += 1
            elif val == low_t:
                count1 += 1
            else:
                count += 1

            # Count affected buildings by usage type if available
            if 'type' in attribute_names:
                usage = attributes[i]['type']
            elif 'TYPE' in attribute_names:
                usage = attributes[i]['TYPE']
            else:
                usage = None
            if 'amenity' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['amenity']
            if 'building_t' in (
                    attribute_names and
                    (usage is None or usage == 0)):
                usage = attributes[i]['building_t']
            if 'office' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['office']
            if 'tourism' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['tourism']
            if 'leisure' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['leisure']
            if 'building' in attribute_names and (usage is None or usage == 0):
                usage = attributes[i]['building']
                if usage == 'yes':
                    usage = 'building'

            if usage is not None and usage != 0:
                key = usage
            else:
                key = 'unknown'

            if key not in buildings:
                buildings[key] = 0
                affected_buildings[key] = 0

            # Count all buildings by type
            buildings[key] += 1
            if val is True:
                # Count affected buildings by type
                affected_buildings[key] += 1

            # Add calculated impact to existing attributes
            if val == high_t:
                attributes[i][self.target_field] = 3
                attributes[i][self.affected_field] = 1

            elif val == medium_t:
                attributes[i][self.target_field] = 2
                attributes[i][self.affected_field] = 1

            elif val == low_t:
                attributes[i][self.target_field] = 1
                attributes[i][self.affected_field] = 1

            else:
                attributes[i][self.target_field] = 0
                attributes[i][self.affected_field] = 0

        # Lump small entries and 'unknown' into 'other' category
        for usage in buildings.keys():
            val = buildings[usage]
            if val < 25 or usage == 'unknown':
                if 'other' not in buildings:
                    buildings['other'] = 0
                    affected_buildings['other'] = 0

                buildings['other'] += val
                affected_buildings['other'] += affected_buildings[usage]
                del buildings[usage]
                del affected_buildings[usage]

        # Generate impact summary
            table_body = [question,
                          TableRow([tr('Hazard Level'),
                                    tr('Number of Buildings')], header=True),
                          TableRow([tr('High Hazard Class'),
                                    format_int(count3)]),
                          TableRow([tr('Medium Hazard Class'),
                                    format_int(count2)]),
                          TableRow([tr('Low Hazard Class'),
                                    format_int(count1)]),
                          TableRow([tr('Total Buildings Affected'),
                                    format_int(count1 + count2 + count3)],
                                   header=True),
                          TableRow([tr('Buildings Not Affected'),
                                    format_int(count)],
                                   header=True),
                          TableRow([tr('All Buildings'), format_int(N)],
                                   header=True)]

        school_closed = 0
        hospital_closed = 0
        # Generate break down by building usage type is available
        list_type_attribute = [
            'TYPE', 'type', 'amenity', 'building_t', 'office',
            'tourism', 'leisure', 'building']
        intersect_type = set(attribute_names) & set(list_type_attribute)
        if len(intersect_type) > 0:
            # Make list of building types
            building_list = []
            for usage in buildings:
                building_type = usage.replace('_', ' ')

                # Lookup internationalised value if available
                building_type = tr(building_type)
                building_list.append([
                    building_type.capitalize(),
                    format_int(affected_buildings[usage]),
                    format_int(buildings[usage])])
                if building_type == 'school':
                    school_closed = affected_buildings[usage]
                if building_type == 'hospital':
                    hospital_closed = affected_buildings[usage]

            # Sort alphabetically
            building_list.sort()

            table_body.append(TableRow(tr('Breakdown by building type'),
                                       header=True))
            for row in building_list:
                s = TableRow(row)
                table_body.append(s)

        table_body.append(TableRow(tr('Action Checklist:'), header=True))
        table_body.append(TableRow(
            tr('Are the critical facilities still open?')))
        table_body.append(TableRow(
            tr('Which structures have warning capacity (eg. sirens, speakers, '
               'etc.)?')))
        table_body.append(TableRow(
            tr('Which buildings will be evacuation centres?')))
        table_body.append(TableRow(
            tr('Where will we locate the operations centre?')))
        table_body.append(TableRow(
            tr('Where will we locate warehouse and/or distribution centres?')))

        if school_closed > 0:
            table_body.append(TableRow(
                tr('Where will the students from the %s closed schools go to '
                   'study?') % format_int(school_closed)))

        if hospital_closed > 0:
            table_body.append(TableRow(
                tr('Where will the patients from the %s closed hospitals go '
                   'for treatment and how will we transport them?') %
                format_int(hospital_closed)))

        table_body.append(TableRow(tr('Notes'), header=True))
        table_body.append(tr('Map shows buildings affected in'
                             ' low, medium and high hazard class areas.'))

        # Result
        impact_summary = Table(table_body).toNewlineFreeString()
        impact_table = impact_summary

        # Create style
        style_classes = [dict(label=tr('High'),
                              value=3,
                              colour='#F31A1C',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Medium'),
                              value=2,
                              colour='#F4A442',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Low'),
                              value=1,
                              colour='#EBF442',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Not Affected'),
                              value=None,
                              colour='#1EFC7C',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2)]
        style_info = dict(target_field=self.target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')

        # For printing map purpose
        map_title = tr('Buildings affected')
        legend_units = tr('(Low, Medium, High)')
        legend_title = tr('Structure inundated status')

        # Create vector layer and return
        vector_layer = Vector(
            data=attributes,
            projection=exposure.get_projection(),
            geometry=exposure.get_geometry(),
            name=tr('Estimated buildings affected'),
            keywords={
                'impact_summary': impact_summary,
                'impact_table': impact_table,
                'target_field': self.affected_field,
                'map_title': map_title,
                'legend_units': legend_units,
                'legend_title': legend_title,
                'buildings_total': N,
                'buildings_affected': count1 + count2 + count3},
            style_info=style_info)
        return vector_layer
コード例 #7
0
ファイル: impact_function.py プロジェクト: sopac/inasafe
    def run(self):
        """Classified hazard impact to buildings (e.g. from Open Street Map).
        """

        # Value from layer's keywords
        structure_class_field = self.exposure.keyword('structure_class_field')
        try:
            exposure_value_mapping = self.exposure.keyword('value_mapping')
        except KeywordNotFoundError:
            # Generic IF, the keyword might not be defined base.py
            exposure_value_mapping = {}
        self.hazard_class_mapping = self.hazard.keyword('value_map')

        keys = [x['key'] for x in generic_raster_hazard_classes['classes']]
        names = [x['name'] for x in generic_raster_hazard_classes['classes']]
        classes = OrderedDict()
        for i in range(len(keys)):
            classes[keys[i]] = names[i]

        # Determine attribute name for hazard class
        hazard_class_attribute = get_non_conflicting_attribute_name(
            'haz_class', [x.keys() for x in self.exposure.layer.data][0])

        interpolated_result = assign_hazard_values_to_exposure_data(
            self.hazard.layer,
            self.exposure.layer,
            attribute_name=hazard_class_attribute,
            mode='constant')

        # Extract relevant exposure data
        attributes = interpolated_result.get_data()

        # Number of building in the interpolated layer
        buildings_total = len(interpolated_result)

        # Inverse the order from low to high
        self.init_report_var(classes.values()[::-1])

        for i in range(buildings_total):
            # Get the usage of the building
            usage = attributes[i][structure_class_field]
            usage = main_type(usage, exposure_value_mapping)

            # Initialize value as Not affected
            attributes[i][self.target_field] = tr('Not affected')
            attributes[i][self.affected_field] = 0

            # Get the hazard level of the building
            level = float(attributes[i][hazard_class_attribute])
            level = float(numpy_round(level))

            # Find the class according the building's level
            for k, v in self.hazard_class_mapping.items():
                if level in v:
                    impact_class = classes[k]
                    # Set the impact level
                    attributes[i][self.target_field] = impact_class
                    # Set to affected
                    attributes[i][self.affected_field] = 1
                    break

            # Count affected buildings by type
            self.classify_feature(attributes[i][self.target_field], usage,
                                  bool(attributes[i][self.affected_field]))

        self.reorder_dictionaries()

        # Create style
        # Low, Medium and High are translated in the attribute table.
        # "Not affected" is not translated in the attribute table.
        style_classes = [
            dict(label=tr('Not Affected'),
                 value='Not affected',
                 colour='#1EFC7C',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Low'),
                 value=tr('Low hazard zone'),
                 colour='#EBF442',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('Medium'),
                 value=tr('Medium hazard zone'),
                 colour='#F4A442',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
            dict(label=tr('High'),
                 value=tr('High hazard zone'),
                 colour='#F31A1C',
                 transparency=0,
                 size=2,
                 border_color='#969696',
                 border_width=0.2),
        ]
        style_info = dict(target_field=self.target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')
        LOGGER.debug('target field : ' + self.target_field)

        impact_data = self.generate_data()

        extra_keywords = {
            'target_field': self.affected_field,
            'map_title': self.map_title(),
            'legend_units': self.metadata().key('legend_units'),
            'legend_title': self.metadata().key('legend_title'),
            'buildings_total': buildings_total,
            'buildings_affected': self.total_affected_buildings
        }

        impact_layer_keywords = self.generate_impact_keywords(extra_keywords)

        # Create impact layer and return
        impact_layer = Vector(data=attributes,
                              projection=self.exposure.layer.get_projection(),
                              geometry=self.exposure.layer.get_geometry(),
                              name=self.map_title(),
                              keywords=impact_layer_keywords,
                              style_info=style_info)

        impact_layer.impact_data = impact_data
        self._impact = impact_layer
        return impact_layer
コード例 #8
0
    def run(self):
        """Classified hazard impact to buildings (e.g. from Open Street Map).
        """

        # Value from layer's keywords

        structure_class_field = self.exposure.keyword('structure_class_field')
        try:
            exposure_value_mapping = self.exposure.keyword('value_mapping')
        except KeywordNotFoundError:
            # Generic IF, the keyword might not be defined base.py
            exposure_value_mapping = {}

        # The 3 classes
        categorical_hazards = self.parameters['Categorical hazards'].value
        low_t = categorical_hazards[0].value
        medium_t = categorical_hazards[1].value
        high_t = categorical_hazards[2].value

        # Determine attribute name for hazard levels
        if self.hazard.layer.is_raster:
            hazard_attribute = 'level'
        else:
            hazard_attribute = None

        interpolated_result = assign_hazard_values_to_exposure_data(
            self.hazard.layer,
            self.exposure.layer,
            attribute_name=hazard_attribute,
            mode='constant')

        # Extract relevant exposure data
        attributes = interpolated_result.get_data()

        buildings_total = len(interpolated_result)

        hazard_classes = [
            tr('Low Hazard Class'),
            tr('Medium Hazard Class'),
            tr('High Hazard Class')
        ]
        self.init_report_var(hazard_classes)

        for i in range(buildings_total):
            usage = attributes[i][structure_class_field]
            usage = main_type(usage, exposure_value_mapping)

            # Count all buildings by type
            attributes[i][self.target_field] = 0
            attributes[i][self.affected_field] = 0
            level = float(attributes[i]['level'])
            level = float(numpy_round(level))
            if level == high_t:
                impact_level = tr('High Hazard Class')
            elif level == medium_t:
                impact_level = tr('Medium Hazard Class')
            elif level == low_t:
                impact_level = tr('Low Hazard Class')
            else:
                continue

            # Add calculated impact to existing attributes
            attributes[i][self.target_field] = {
                tr('High Hazard Class'): 3,
                tr('Medium Hazard Class'): 2,
                tr('Low Hazard Class'): 1
            }[impact_level]
            attributes[i][self.affected_field] = 1
            # Count affected buildings by type
            self.classify_feature(impact_level, usage, True)

        self.reorder_dictionaries()

        # Consolidate the small building usage groups < 25 to other
        # Building threshold #2468
        postprocessors = self.parameters['postprocessors']
        building_postprocessors = postprocessors['BuildingType'][0]
        self.building_report_threshold = building_postprocessors.value[0].value
        self._consolidate_to_other()

        # Create style
        style_classes = [
            dict(
                label=tr('Not Affected'),
                value=None,
                colour='#1EFC7C',
                transparency=0,
                size=2,
                border_color='#969696',
                border_width=0.2),
            dict(
                label=tr('Low'),
                value=1,
                colour='#EBF442',
                transparency=0,
                size=2,
                border_color='#969696',
                border_width=0.2),
            dict(
                label=tr('Medium'),
                value=2,
                colour='#F4A442',
                transparency=0,
                size=2,
                border_color='#969696',
                border_width=0.2),
            dict(
                label=tr('High'),
                value=3,
                colour='#F31A1C',
                transparency=0,
                size=2,
                border_color='#969696',
                border_width=0.2),
        ]
        style_info = dict(
            target_field=self.target_field,
            style_classes=style_classes,
            style_type='categorizedSymbol')

        impact_data = self.generate_data()

        extra_keywords = {
            'target_field': self.affected_field,
            'map_title': self.metadata().key('map_title'),
            'legend_units': self.metadata().key('legend_units'),
            'legend_title': self.metadata().key('legend_title'),
            'buildings_total': buildings_total,
            'buildings_affected': self.total_affected_buildings
        }

        impact_layer_keywords = self.generate_impact_keywords(extra_keywords)

        # Create impact layer and return
        impact_layer = Vector(
            data=attributes,
            projection=self.exposure.layer.get_projection(),
            geometry=self.exposure.layer.get_geometry(),
            name=self.metadata().key('layer_name'),
            keywords=impact_layer_keywords,
            style_info=style_info)

        impact_layer.impact_data = impact_data
        self._impact = impact_layer
        return impact_layer
コード例 #9
0
    def run(self):
        """Classified hazard impact to buildings (e.g. from Open Street Map).
        """
        self.validate()
        self.prepare()

        self.provenance.append_step("Calculating Step", "Impact function is calculating the impact.")

        # Value from layer's keywords
        # Try to get the value from keyword, if not exist, it will not fail,
        # but use the old get_osm_building_usage
        try:
            structure_class_field = self.exposure.keyword("structure_class_field")
        except KeywordNotFoundError:
            structure_class_field = None

        # The 3 classes
        categorical_hazards = self.parameters["Categorical hazards"].value
        low_t = categorical_hazards[0].value
        medium_t = categorical_hazards[1].value
        high_t = categorical_hazards[2].value

        # Determine attribute name for hazard levels
        if self.hazard.layer.is_raster:
            hazard_attribute = "level"
        else:
            hazard_attribute = None

        interpolated_result = assign_hazard_values_to_exposure_data(
            self.hazard.layer, self.exposure.layer, attribute_name=hazard_attribute, mode="constant"
        )

        # Extract relevant exposure data
        attribute_names = interpolated_result.get_attribute_names()
        attributes = interpolated_result.get_data()

        buildings_total = len(interpolated_result)
        # Calculate building impact
        self.buildings = {}
        self.affected_buildings = OrderedDict(
            [(tr("High Hazard Class"), {}), (tr("Medium Hazard Class"), {}), (tr("Low Hazard Class"), {})]
        )
        for i in range(buildings_total):

            if structure_class_field and structure_class_field in attribute_names:
                usage = attributes[i][structure_class_field]
            else:
                usage = get_osm_building_usage(attribute_names, attributes[i])

            if usage is None or usage == 0:
                usage = "unknown"

            if usage not in self.buildings:
                self.buildings[usage] = 0
                for category in self.affected_buildings.keys():
                    self.affected_buildings[category][usage] = OrderedDict([(tr("Buildings Affected"), 0)])

            # Count all buildings by type
            self.buildings[usage] += 1
            attributes[i][self.target_field] = 0
            attributes[i][self.affected_field] = 0
            level = float(attributes[i]["level"])
            level = float(numpy_round(level))
            if level == high_t:
                impact_level = tr("High Hazard Class")
            elif level == medium_t:
                impact_level = tr("Medium Hazard Class")
            elif level == low_t:
                impact_level = tr("Low Hazard Class")
            else:
                continue

            # Add calculated impact to existing attributes
            attributes[i][self.target_field] = {
                tr("High Hazard Class"): 3,
                tr("Medium Hazard Class"): 2,
                tr("Low Hazard Class"): 1,
            }[impact_level]
            attributes[i][self.affected_field] = 1
            # Count affected buildings by type
            self.affected_buildings[impact_level][usage][tr("Buildings Affected")] += 1

        # Consolidate the small building usage groups < 25 to other
        # Building threshold #2468
        postprocessors = self.parameters["postprocessors"]
        building_postprocessors = postprocessors["BuildingType"][0]
        self.building_report_threshold = building_postprocessors.value[0].value
        self._consolidate_to_other()

        # Create style
        style_classes = [
            dict(
                label=tr("High"),
                value=3,
                colour="#F31A1C",
                transparency=0,
                size=2,
                border_color="#969696",
                border_width=0.2,
            ),
            dict(
                label=tr("Medium"),
                value=2,
                colour="#F4A442",
                transparency=0,
                size=2,
                border_color="#969696",
                border_width=0.2,
            ),
            dict(
                label=tr("Low"),
                value=1,
                colour="#EBF442",
                transparency=0,
                size=2,
                border_color="#969696",
                border_width=0.2,
            ),
            dict(
                label=tr("Not Affected"),
                value=None,
                colour="#1EFC7C",
                transparency=0,
                size=2,
                border_color="#969696",
                border_width=0.2,
            ),
        ]
        style_info = dict(target_field=self.target_field, style_classes=style_classes, style_type="categorizedSymbol")

        impact_table = impact_summary = self.html_report()

        # For printing map purpose
        map_title = tr("Buildings affected")
        legend_title = tr("Structure inundated status")
        legend_units = tr("(Low, Medium, High)")

        extra_keywords = {
            "impact_summary": impact_summary,
            "impact_table": impact_table,
            "target_field": self.affected_field,
            "map_title": map_title,
            "legend_units": legend_units,
            "legend_title": legend_title,
            "buildings_total": buildings_total,
            "buildings_affected": self.total_affected_buildings,
        }

        self.set_if_provenance()

        impact_layer_keywords = self.generate_impact_keywords(extra_keywords)

        # Create vector layer and return
        vector_layer = Vector(
            data=attributes,
            projection=self.exposure.layer.get_projection(),
            geometry=self.exposure.layer.get_geometry(),
            name=tr("Estimated buildings affected"),
            keywords=impact_layer_keywords,
            style_info=style_info,
        )
        self._impact = vector_layer
        return vector_layer
コード例 #10
0
    def run(self, layers=None):
        """Classified hazard impact to buildings (e.g. from Open Street Map).

         :param layers: List of layers expected to contain.
                * hazard: Classified Hazard layer
                * exposure: Vector layer of structure data on
                the same grid as hazard
        """
        self.validate()
        self.prepare(layers)

        # The 3 classes
        low_t = self.parameters['low_hazard_class']
        medium_t = self.parameters['medium_hazard_class']
        high_t = self.parameters['high_hazard_class']

        # Extract data
        hazard = self.hazard      # Classified Hazard
        exposure = self.exposure  # Building locations

        # Determine attribute name for hazard levels
        if hazard.is_raster:
            hazard_attribute = 'level'
        else:
            hazard_attribute = None

        interpolated_result = assign_hazard_values_to_exposure_data(
            hazard,
            exposure,
            attribute_name=hazard_attribute,
            mode='constant')

        # Extract relevant exposure data
        attribute_names = interpolated_result.get_attribute_names()
        attributes = interpolated_result.get_data()

        buildings_total = len(interpolated_result)
        # Calculate building impact
        self.buildings = {}
        self.affected_buildings = OrderedDict([
            (tr('High Hazard Class'), {}),
            (tr('Medium Hazard Class'), {}),
            (tr('Low Hazard Class'), {})
        ])
        for i in range(buildings_total):
            usage = get_osm_building_usage(attribute_names, attributes[i])
            if usage is None or usage == 0:
                usage = 'unknown'

            if usage not in self.buildings:
                self.buildings[usage] = 0
                for category in self.affected_buildings.keys():
                    self.affected_buildings[category][usage] = OrderedDict([
                        (tr('Buildings Affected'), 0)])

            # Count all buildings by type
            self.buildings[usage] += 1
            attributes[i][self.target_field] = 0
            attributes[i][self.affected_field] = 0
            level = float(attributes[i]['level'])
            level = float(numpy_round(level))
            if level == high_t:
                impact_level = tr('High Hazard Class')
            elif level == medium_t:
                impact_level = tr('Medium Hazard Class')
            elif level == low_t:
                impact_level = tr('Low Hazard Class')
            else:
                continue

            # Add calculated impact to existing attributes
            attributes[i][self.target_field] = {
                tr('High Hazard Class'): 3,
                tr('Medium Hazard Class'): 2,
                tr('Low Hazard Class'): 1
            }[impact_level]
            attributes[i][self.affected_field] = 1
            # Count affected buildings by type
            self.affected_buildings[impact_level][usage][
                tr('Buildings Affected')] += 1

        # Consolidate the small building usage groups < 25 to other
        self._consolidate_to_other()

        # Create style
        style_classes = [dict(label=tr('High'),
                              value=3,
                              colour='#F31A1C',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Medium'),
                              value=2,
                              colour='#F4A442',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Low'),
                              value=1,
                              colour='#EBF442',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2),
                         dict(label=tr('Not Affected'),
                              value=None,
                              colour='#1EFC7C',
                              transparency=0,
                              size=2,
                              border_color='#969696',
                              border_width=0.2)]
        style_info = dict(target_field=self.target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')

        impact_table = impact_summary = self.generate_html_report()
        # For printing map purpose
        map_title = tr('Buildings affected')
        legend_units = tr('(Low, Medium, High)')
        legend_title = tr('Structure inundated status')

        # Create vector layer and return
        vector_layer = Vector(
            data=attributes,
            projection=exposure.get_projection(),
            geometry=exposure.get_geometry(),
            name=tr('Estimated buildings affected'),
            keywords={
                'impact_summary': impact_summary,
                'impact_table': impact_table,
                'target_field': self.affected_field,
                'map_title': map_title,
                'legend_units': legend_units,
                'legend_title': legend_title,
                'buildings_total': buildings_total,
                'buildings_affected': self.total_affected_buildings},
            style_info=style_info)
        self._impact = vector_layer
        return vector_layer