Example #1
0
    def test_pre_processors_nearby_places(self):
        """Test the pre_processors_nearby_places"""
        hazard_layer = load_test_raster_layer('gisv4', 'hazard',
                                              'earthquake.asc')
        exposure_layer = load_test_vector_layer('gisv4', 'exposure',
                                                'building-points.geojson')
        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        status, message = impact_function.prepare()
        self.assertEqual(PREPARE_SUCCESS, status, message)

        # The exposure is not place but buildings
        self.assertFalse(
            pre_processors_nearby_places['condition'](impact_function))

        hazard_layer = load_test_raster_layer('gisv4', 'hazard',
                                              'earthquake.asc')
        exposure_layer = load_test_vector_layer('gisv4', 'exposure',
                                                'places.geojson')
        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        status, message = impact_function.prepare()
        self.assertEqual(PREPARE_SUCCESS, status, message)

        # EQ on places, it must be OK.
        self.assertTrue(
            pre_processors_nearby_places['condition'](impact_function))
Example #2
0
    def test_pre_processors_earthquake_contour(self):
        """Test the pre_processors_earthquake_contour"""
        hazard_layer = load_test_raster_layer('gisv4', 'hazard',
                                              'earthquake.asc')
        exposure_layer = load_test_vector_layer('gisv4', 'exposure',
                                                'building-points.geojson')
        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        status, message = impact_function.prepare()
        self.assertEqual(PREPARE_SUCCESS, status, message)

        self.assertTrue(
            pre_processor_earthquake_contour['condition'](impact_function))

        hazard_layer = load_test_raster_layer('hazard',
                                              'classified_flood_20_20.asc')
        exposure_layer = load_test_vector_layer('gisv4', 'exposure',
                                                'places.geojson')
        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        status, message = impact_function.prepare()
        self.assertEqual(PREPARE_SUCCESS, status, message)

        # not ok, since the hazard is flood, not earthquake
        self.assertFalse(
            pre_processor_earthquake_contour['condition'](impact_function))
Example #3
0
    def test_pre_processors_earthquake_contour(self):
        """Test the pre_processors_earthquake_contour"""
        hazard_layer = load_test_raster_layer(
            'gisv4', 'hazard', 'earthquake.asc')
        exposure_layer = load_test_vector_layer(
            'gisv4', 'exposure', 'building-points.geojson')
        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        status, message = impact_function.prepare()
        self.assertEqual(PREPARE_SUCCESS, status, message)

        self.assertTrue(
            pre_processor_earthquake_contour['condition'](impact_function))

        hazard_layer = load_test_raster_layer(
            'hazard', 'classified_flood_20_20.asc')
        exposure_layer = load_test_vector_layer(
            'gisv4', 'exposure', 'places.geojson')
        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        status, message = impact_function.prepare()
        self.assertEqual(PREPARE_SUCCESS, status, message)

        # not ok, since the hazard is flood, not earthquake
        self.assertFalse(
            pre_processor_earthquake_contour['condition'](impact_function))
Example #4
0
    def test_pre_processors_nearby_places(self):
        """Test the pre_processors_nearby_places"""
        hazard_layer = load_test_raster_layer(
            'gisv4', 'hazard', 'earthquake.asc')
        exposure_layer = load_test_vector_layer(
            'gisv4', 'exposure', 'building-points.geojson')
        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        status, message = impact_function.prepare()
        self.assertEqual(PREPARE_SUCCESS, status, message)

        # The exposure is not place but buildings
        self.assertFalse(
            pre_processors_nearby_places['condition'](impact_function))

        hazard_layer = load_test_raster_layer(
            'gisv4', 'hazard', 'earthquake.asc')
        exposure_layer = load_test_vector_layer(
            'gisv4', 'exposure', 'places.geojson')
        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        status, message = impact_function.prepare()
        self.assertEqual(PREPARE_SUCCESS, status, message)

        # EQ on places, it must be OK.
        self.assertTrue(
            pre_processors_nearby_places['condition'](impact_function))
Example #5
0
    def prepare_impact_function(self):
        """Create analysis as a representation of current situation of IFCW."""

        # Impact Functions
        impact_function = ImpactFunction()
        impact_function.callback = self.progress_callback

        # Layers
        impact_function.hazard = self.parent.hazard_layer
        impact_function.exposure = self.parent.exposure_layer
        aggregation = self.parent.aggregation_layer

        if aggregation:
            impact_function.aggregation = aggregation
            impact_function.use_selected_features_only = (setting(
                'useSelectedFeaturesOnly', False, bool))
        else:
            # self.extent.crs is the map canvas CRS.
            impact_function.crs = self.extent.crs
            mode = setting('analysis_extents_mode')
            if self.extent.user_extent:
                # This like a hack to transform a geometry to a rectangle.
                # self.extent.user_extent is a QgsGeometry.
                # impact_function.requested_extent needs a QgsRectangle.
                wkt = self.extent.user_extent.asWkt()
                impact_function.requested_extent = wkt_to_rectangle(wkt)

            elif mode == HAZARD_EXPOSURE_VIEW:
                impact_function.requested_extent = (
                    self.iface.mapCanvas().extent())

            elif mode == EXPOSURE:
                impact_function.use_exposure_view_only = True

        # We don't have any checkbox in the wizard for the debug mode.
        impact_function.debug_mode = False

        return impact_function
Example #6
0
    def prepare_impact_function(self):
        """Create analysis as a representation of current situation of IFCW."""

        # Impact Functions
        impact_function = ImpactFunction()
        impact_function.callback = self.progress_callback

        # Layers
        impact_function.hazard = self.parent.hazard_layer
        impact_function.exposure = self.parent.exposure_layer
        aggregation = self.parent.aggregation_layer

        if aggregation:
            impact_function.aggregation = aggregation
            impact_function.use_selected_features_only = (
                setting('useSelectedFeaturesOnly', False, bool))
        else:
            # self.extent.crs is the map canvas CRS.
            impact_function.crs = self.extent.crs
            mode = setting('analysis_extents_mode')
            if self.extent.user_extent:
                # This like a hack to transform a geometry to a rectangle.
                # self.extent.user_extent is a QgsGeometry.
                # impact_function.requested_extent needs a QgsRectangle.
                wkt = self.extent.user_extent.asWkt()
                impact_function.requested_extent = wkt_to_rectangle(wkt)

            elif mode == HAZARD_EXPOSURE_VIEW:
                impact_function.requested_extent = (
                    self.iface.mapCanvas().extent())

            elif mode == EXPOSURE:
                impact_function.use_exposure_view_only = True

        # We don't have any checkbox in the wizard for the debug mode.
        impact_function.debug_mode = False

        return impact_function
    def test_earthquake_population_without_aggregation(self):
        """Testing Earthquake in Population without aggregation.

        .. versionadded:: 4.0
        """
        output_folder = self.fixtures_dir('../output/earthquake_population')

        # Classified vector with building-points
        shutil.rmtree(output_folder, ignore_errors=True)

        hazard_layer = load_test_raster_layer('hazard', 'earthquake.tif')
        exposure_layer = load_test_raster_layer('exposure',
                                                'pop_binary_raster_20_20.asc')

        impact_function = ImpactFunction()
        impact_function.exposure = exposure_layer
        impact_function.hazard = hazard_layer
        impact_function.crs = QgsCoordinateReferenceSystem(4326)
        impact_function.prepare()
        return_code, message = impact_function.run()

        self.assertEqual(return_code, ANALYSIS_SUCCESS, message)

        report_metadata = ReportMetadata(
            metadata_dict=standard_impact_report_metadata_html)

        impact_report = ImpactReport(IFACE,
                                     report_metadata,
                                     impact_function=impact_function)
        impact_report.output_folder = output_folder
        return_code, message = impact_report.process_components()

        self.assertEqual(return_code, ImpactReport.REPORT_GENERATION_SUCCESS,
                         message)
        """Checking generated context."""
        empty_component_output_message = 'Empty component output'

        # Check Analysis Summary
        analysis_summary = impact_report.metadata.component_by_key(
            general_report_component['key'])
        """:type: safe.report.report_metadata.Jinja2ComponentsMetadata"""

        expected_context = {
            'table_header':
            (u'Estimated Number of people affected per MMI intensity'),
            'header':
            u'General Report',
            'summary': [{
                'header_label':
                u'Hazard Zone',
                'rows': [{
                    'numbers': ['0'],
                    'name': u'X',
                    'key': 'X'
                }, {
                    'numbers': ['0'],
                    'name': u'IX',
                    'key': 'IX'
                }, {
                    'numbers': ['200'],
                    'name': u'VIII',
                    'key': 'VIII'
                }, {
                    'numbers': ['0'],
                    'name': u'VII',
                    'key': 'VII'
                }, {
                    'numbers': ['0'],
                    'name': u'VI',
                    'key': 'VI'
                }, {
                    'numbers': ['0'],
                    'name': u'V',
                    'key': 'V'
                }, {
                    'numbers': ['0'],
                    'name': u'IV',
                    'key': 'IV'
                }, {
                    'numbers': ['0'],
                    'name': u'III',
                    'key': 'III'
                }, {
                    'numbers': ['0'],
                    'name': u'II',
                    'key': 'II'
                }, {
                    'numbers': ['0'],
                    'name': u'I',
                    'key': 'I'
                }, {
                    'as_header': True,
                    'key': 'total_exposed_field',
                    'name': u'Total Exposed',
                    'numbers': ['200']
                }],
                'value_labels': [u'Count']
            }, {
                'header_label':
                u'Population',
                'rows': [{
                    'numbers': ['200'],
                    'name': u'Affected',
                    'key': 'total_affected_field',
                }, {
                    'key': 'total_not_affected_field',
                    'name': u'Not Affected',
                    'numbers': ['0']
                }, {
                    'key': 'total_not_exposed_field',
                    'name': u'Not Exposed',
                    'numbers': ['0']
                }, {
                    'numbers': ['200'],
                    'name': u'Displaced',
                    'key': 'displaced_field'
                }, {
                    'numbers': ['0 - 100'],
                    'name': u'Fatalities',
                    'key': 'fatalities_field'
                }],
                'value_labels': [u'Count']
            }],
            'notes': [
                u'Exposed People: People who are present in hazard zones and '
                u'are thereby subject to potential losses. In InaSAFE, people '
                u'who are exposed are those people who are within the extent '
                u'of the hazard.',
                u'Affected People: People who are affected by a hazardous '
                u'event. People can be affected directly or indirectly. '
                u'Affected people may experience short-term or long-term '
                u'consequences to their lives, livelihoods or health and in '
                u'the economic, physical, social, cultural and environmental '
                u'assets. In InaSAFE, people who are killed during the event '
                u'are also considered affected.',
                u'Displaced People: Displaced people are people who, for '
                u'different reasons and circumstances because of risk or '
                u'disaster, have to leave their place of residence. '
                u'In InaSAFE, demographic and minimum needs reports are based '
                u'on displaced / evacuated people.'
            ]
        }
        actual_context = analysis_summary.context

        self.assertDictEqual(expected_context, actual_context)
        self.assertTrue(analysis_summary.output,
                        empty_component_output_message)

        report_metadata = ReportMetadata(metadata_dict=infographic_report)
        infographic_impact_report = ImpactReport(
            IFACE, report_metadata, impact_function=impact_function)

        infographic_impact_report.output_folder = output_folder
        return_code, message = infographic_impact_report.process_components()

        self.assertEqual(return_code, ImpactReport.REPORT_GENERATION_SUCCESS,
                         message)

        # check population pie chart if we have 100% donut slice
        population_chart_svg = (
            infographic_impact_report.metadata.component_by_key(
                population_chart_svg_component['key']))

        expected_slices = [{
            'value':
            200,
            'show_label':
            True,
            'center': (224.0, 128.0),
            'stroke_opacity':
            1,
            'path':
            'M128.000000,0.000000a128.000000,128.000000 0 0 1 '
            '0.000000,256.000000l-0.000000,-64.000000a64.000000,'
            '64.000000 0 0 0 0.000000,-128.000000Z',
            'percentage':
            100,
            'label':
            u'VIII',
            'stroke':
            u'#ff7000',
            'label_position': (256, 0),
            'fill':
            u'#ff7000'
        }, {
            'value':
            100,
            'show_label':
            False,
            'center': (32.0, 128.0),
            'stroke_opacity':
            1,
            'path':
            'M128.000000,256.000000a128.000000,128.000000 0 0 1 '
            '-0.000000,-256.000000l0.000000,64.000000a64.000000,'
            '64.000000 0 0 0 0.000000,128.000000Z',
            'percentage':
            50.0,
            'label':
            '',
            'stroke':
            u'#ff7000',
            'label_position': (256, 0),
            'fill':
            u'#ff7000'
        }, {
            'value':
            0,
            'show_label':
            False,
            'center': (128.0, 224.0),
            'stroke_opacity':
            1,
            'path':
            'M128.000000,256.000000a128.000000,128.000000 0 0 1 '
            '0.000000,0.000000l-0.000000,-64.000000a64.000000,'
            '64.000000 0 0 0 0.000000,0.000000Z',
            'percentage':
            0.0,
            'label':
            u'Total Not Affected',
            'stroke':
            '#fff',
            'label_position': (256, 0),
            'fill':
            u'#1a9641'
        }]

        actual_context = population_chart_svg.context['context']
        actual_slices = actual_context.slices

        self.assertEqual(expected_slices, actual_slices)
        self.assertTrue(population_chart_svg.output,
                        empty_component_output_message)

        shutil.rmtree(output_folder, ignore_errors=True)
Example #8
0
    def run_task(self, task_item, status_item, count=0, index=''):
        """Run a single task.

        :param task_item: Table task_item containing task name / details.
        :type task_item: QTableWidgetItem

        :param status_item: Table task_item that holds the task status.
        :type status_item: QTableWidgetItem

        :param count: Count of scenarios that have been run already.
        :type count:

        :param index: The index for the table item that will be run.
        :type index: int

        :returns: Flag indicating if the task succeeded or not.
        :rtype: bool
        """
        self.enable_busy_cursor()
        for layer_group in self.layer_group_container:
            layer_group.setItemVisibilityChecked(False)

        # set status to 'running'
        status_item.setText(self.tr('Running'))

        # .. see also:: :func:`appendRow` to understand the next 2 lines
        variant = task_item.data(QtCore.Qt.UserRole)
        value = variant[0]
        result = True

        if isinstance(value, str):
            filename = value
            # run script
            try:
                self.run_script(filename)
                # set status to 'OK'
                status_item.setText(self.tr('Script OK'))
            except Exception as e:  # pylint: disable=W0703
                # set status to 'fail'
                status_item.setText(self.tr('Script Fail'))

                LOGGER.exception(
                    'Running macro failed. The exception: ' + str(e))
                result = False
        elif isinstance(value, dict):
            # start in new project if toggle is active
            if self.start_in_new_project:
                self.iface.newProject()
            # create layer group
            group_name = value['scenario_name']
            self.layer_group = self.root.addGroup(group_name)
            self.layer_group_container.append(self.layer_group)

            # Its a dict containing files for a scenario
            success, parameters = self.prepare_task(value)
            if not success:
                # set status to 'running'
                status_item.setText(self.tr('Please update scenario'))
                self.disable_busy_cursor()
                return False

            directory = self.output_directory.text()
            if self.scenario_directory_radio.isChecked():
                directory = self.source_directory.text()

            output_directory = os.path.join(directory, group_name)
            if not os.path.exists(output_directory):
                os.makedirs(output_directory)

            # If impact function parameters loaded successfully, initiate IF.
            impact_function = ImpactFunction()
            impact_function.datastore = Folder(output_directory)
            impact_function.datastore.default_vector_format = "geojson"
            impact_function.hazard = parameters[layer_purpose_hazard['key']]
            impact_function.exposure = (
                parameters[layer_purpose_exposure['key']])
            if parameters[layer_purpose_aggregation['key']]:
                impact_function.aggregation = (
                    parameters[layer_purpose_aggregation['key']])
            elif parameters['extent']:
                impact_function.requested_extent = parameters['extent']
                impact_function.crs = parameters['crs']
            prepare_status, prepare_message = impact_function.prepare()
            if prepare_status == PREPARE_SUCCESS:
                LOGGER.info('Impact function ready')
                status, message = impact_function.run()
                if status == ANALYSIS_SUCCESS:
                    status_item.setText(self.tr('Analysis Success'))
                    impact_layer = impact_function.impact
                    if impact_layer.isValid():
                        layer_list = [
                            impact_layer,
                            impact_function.analysis_impacted,
                            parameters[layer_purpose_hazard['key']],
                            parameters[layer_purpose_exposure['key']],
                            parameters[layer_purpose_aggregation['key']]]
                        QgsProject.instance().addMapLayers(
                            layer_list, False)
                        for layer in layer_list:
                            self.layer_group.addLayer(layer)
                        map_canvas = QgsProject.instance().mapLayers()
                        for layer in map_canvas:
                            # turn of layer visibility if not impact layer
                            if map_canvas[layer].id() == impact_layer.id():
                                self.set_layer_visible(
                                    map_canvas[layer], True)
                            else:
                                self.set_layer_visible(
                                    map_canvas[layer], False)

                        # we need to set analysis_impacted as an active layer
                        # because we need to get all qgis variables that we
                        # need from this layer for infographic.
                        if self.iface:
                            self.iface.setActiveLayer(
                                impact_function.analysis_impacted)

                        report_directory = os.path.join(
                            output_directory, 'output')

                        # generate map report and impact report
                        try:
                            error_code, message = (
                                impact_function.generate_report(
                                    all_default_report_components,
                                    report_directory))

                        except BaseException:
                            status_item.setText(
                                self.tr('Report failed to generate.'))
                    else:
                        LOGGER.info('Impact layer is invalid')

                elif status == ANALYSIS_FAILED_BAD_INPUT:
                    LOGGER.info('Bad input detected')

                elif status == ANALYSIS_FAILED_BAD_CODE:
                    LOGGER.info(
                        'Impact function encountered a bug: %s' % message)

            else:
                LOGGER.warning('Impact function not ready')
                send_error_message(self, prepare_message)

        else:
            LOGGER.exception('Data type not supported: "%s"' % value)
            result = False

        self.disable_busy_cursor()
        return result