Ejemplo n.º 1
0
    def test_result_styling(self):
        """Test that ouputs from a model are correctly styled (colours and
        opacity. """

        # Push OK with the left mouse button

        print '--------------------'
        print combos_to_string(DOCK)

        result, message = setup_scenario(
            DOCK,
            hazard='A flood in Jakarta like in 2007',
            exposure='People',
            function='Need evacuation',
            function_id='Flood Evacuation Function')
        self.assertTrue(result, message)

        # Enable on-the-fly reprojection
        set_canvas_crs(GEOCRS, True)
        set_jakarta_extent(DOCK)

        DOCK.accept()
        # DOCK.analysis.get_impact_layer()
        safe_layer = DOCK.analysis.get_impact_layer()
        qgis_layer = read_impact_layer(safe_layer)
        style = safe_layer.get_style_info()
        setRasterStyle(qgis_layer, style)
        # simple test for now - we could test explicity for style state
        # later if needed.
        message = ('Raster layer was not assigned a Singleband pseudocolor'
                   ' renderer as expected.')
        self.assertTrue(
            qgis_layer.renderer().type() == 'singlebandpseudocolor', message)
Ejemplo n.º 2
0
    def completed(self, zero_impact):
        """Slot activated when the process is done.

        :param zero_impact: Flag for zero impact.
        :type zero_impact: bool

        .. note:: Adapted from the dock
        """

        # Try to run completion code
        # Show the result in the dock from layer if there is an impact.
        if not zero_impact:
            try:
                from datetime import datetime
                LOGGER.debug(datetime.now())
                LOGGER.debug('get engine impact layer')
                LOGGER.debug(self.impact_function is None)

                # Load impact layer into QGIS
                qgis_impact_layer = read_impact_layer(
                    self.impact_function.impact)
                report = self.show_results()

            except Exception, e:  # pylint: disable=W0703
                # FIXME (Ole): This branch is not covered by the tests
                self.analysis_error(e, self.tr('Error loading impact layer.'))
            else:
                # On success, display generated report
                impact_path = qgis_impact_layer.source()
                message = m.Message(report)
                # noinspection PyTypeChecker
                send_static_message(self, message)
                self.parent.step_fc_analysis.wvResults.impact_path = \
                    impact_path
Ejemplo n.º 3
0
    def test_result_styling(self):
        """Test that colours and opacity from a model are correctly styled."""

        # Push OK with the left mouse button

        print '--------------------'
        print combos_to_string(self.dock)

        result, message = setup_scenario(
            self.dock,
            hazard='Continuous Flood',
            exposure='Population',
            function='Need evacuation',
            function_id='FloodEvacuationRasterHazardFunction')
        self.assertTrue(result, message)

        # Enable on-the-fly reprojection
        set_canvas_crs(GEOCRS, True)
        set_jakarta_extent(self.dock)

        self.dock.accept()
        # self.dock.analysis.get_impact_layer()
        safe_layer = self.dock.analysis.impact_layer
        qgis_layer = read_impact_layer(safe_layer)
        style = safe_layer.get_style_info()
        setRasterStyle(qgis_layer, style)
        # simple test for now - we could test explicity for style state
        # later if needed.
        message = (
            'Raster layer was not assigned a Singleband pseudocolor'
            ' renderer as expected.')
        self.assertTrue(
            qgis_layer.renderer().type() == 'singlebandpseudocolor', message)
Ejemplo n.º 4
0
    def test_result_styling(self):
        """Test that colours and opacity from a model are correctly styled."""

        settings = QtCore.QSettings()
        settings.setValue('inasafe/analysis_extents_mode', 'HazardExposure')

        result, message = setup_scenario(
            self.dock,
            hazard='Continuous Flood',
            exposure='Population',
            function='Need evacuation',
            function_id='FloodEvacuationRasterHazardFunction')
        self.assertTrue(result, message)

        # Enable on-the-fly reprojection
        set_canvas_crs(GEOCRS, True)
        set_jakarta_extent(self.dock)

        self.dock.accept()
        safe_layer = self.dock.impact_function.impact
        qgis_layer = read_impact_layer(safe_layer)
        style = safe_layer.get_style_info()
        setRasterStyle(qgis_layer, style)
        # simple test for now - we could test explicitly for style state
        # later if needed.
        message = (
            'Raster layer was not assigned a Singleband pseudocolor '
            'renderer as expected.')
        self.assertEquals(
            qgis_layer.renderer().type(), 'singlebandpseudocolor', message)
Ejemplo n.º 5
0
    def test_result_styling(self):
        """Test that colours and opacity from a model are correctly styled."""

        settings = QtCore.QSettings()
        settings.setValue('inasafe/analysis_extents_mode', 'HazardExposure')

        result, message = setup_scenario(
            self.dock,
            hazard='Continuous Flood',
            exposure='Population',
            function='Need evacuation',
            function_id='FloodEvacuationRasterHazardFunction')
        self.assertTrue(result, message)

        # Enable on-the-fly reprojection
        set_canvas_crs(GEOCRS, True)
        set_jakarta_extent(self.dock)

        self.dock.accept()
        safe_layer = self.dock.impact_function.impact
        qgis_layer = read_impact_layer(safe_layer)
        style = safe_layer.get_style_info()
        setRasterStyle(qgis_layer, style)
        # simple test for now - we could test explicitly for style state
        # later if needed.
        message = ('Raster layer was not assigned a Singleband pseudocolor '
                   'renderer as expected.')
        self.assertEquals(qgis_layer.renderer().type(),
                          'singlebandpseudocolor', message)
Ejemplo n.º 6
0
    def completed(self, zero_impact):
        """Slot activated when the process is done.

        :param zero_impact: Flag for zero impact.
        :type zero_impact: bool

        .. note:: Adapted from the dock
        """

        # Try to run completion code
        # Show the result in the dock from layer if there is an impact.
        if not zero_impact:
            try:
                from datetime import datetime
                LOGGER.debug(datetime.now())
                LOGGER.debug('get engine impact layer')
                LOGGER.debug(self.impact_function is None)

                # Load impact layer into QGIS
                qgis_impact_layer = read_impact_layer(
                    self.impact_function.impact)
                report = self.show_results()

            except Exception, e:  # pylint: disable=W0703
                # FIXME (Ole): This branch is not covered by the tests
                self.analysis_error(e, self.tr('Error loading impact layer.'))
            else:
                # On success, display generated report
                impact_path = qgis_impact_layer.source()
                message = m.Message(report)
                # noinspection PyTypeChecker
                send_static_message(self, message)
                self.parent.step_fc_analysis.wvResults.impact_path = \
                    impact_path
Ejemplo n.º 7
0
    def completed(self):
        """Slot activated when the process is done.

        .. note:: Adapted from the dock
        """

        # Try to run completion code
        try:
            from datetime import datetime
            LOGGER.debug(datetime.now())
            LOGGER.debug('get engine impact layer')
            LOGGER.debug(self.impact_function is None)

            # Load impact layer into QGIS
            qgis_impact_layer = read_impact_layer(self.impact_function.impact)
            report = self.show_results()

        except Exception, e:  # pylint: disable=W0703
            # FIXME (Ole): This branch is not covered by the tests
            self.analysis_error(e, self.tr('Error loading impact layer.'))
Ejemplo n.º 8
0
    def completed(self):
        """Slot activated when the process is done.

        .. note:: Adapted from the dock
        """

        # Try to run completion code
        try:
            from datetime import datetime
            LOGGER.debug(datetime.now())
            LOGGER.debug('get engine impact layer')
            LOGGER.debug(self.analysis is None)
            engine_impact_layer = self.analysis.get_impact_layer()

            # Load impact layer into QGIS
            qgis_impact_layer = read_impact_layer(engine_impact_layer)

            report = self.show_results(qgis_impact_layer, engine_impact_layer)

        except Exception, e:  # pylint: disable=W0703
            # FIXME (Ole): This branch is not covered by the tests
            self.analysis_error(e, self.tr('Error loading impact layer.'))
Ejemplo n.º 9
0
    def show_results(self):
        """Helper function for slot activated when the process is done.

        .. versionchanged:: 3.4 - removed parameters.

        .. note:: If you update this function, please report your change to
            safe.gui.widgets.dock.show_results too.

        :returns: Provides a report for writing to the dock.
        :rtype: str
        """
        qgis_exposure = self.impact_function.exposure.qgis_layer()
        qgis_hazard = self.impact_function.hazard.qgis_layer()
        qgis_aggregation = self.impact_function.aggregation.qgis_layer()

        safe_impact_layer = self.impact_function.impact
        qgis_impact_layer = read_impact_layer(safe_impact_layer)

        keywords = self.keyword_io.read_keywords(qgis_impact_layer)
        json_path = os.path.splitext(qgis_impact_layer.source())[0] + '.json'

        # write postprocessing report to keyword
        postprocessor_data = self.impact_function.postprocessor_manager.\
            get_json_data(self.impact_function.aggregator.aoi_mode)
        post_processing_report = m.Message()
        if os.path.exists(json_path):
            with open(json_path) as json_file:
                impact_data = json.load(
                    json_file, object_pairs_hook=OrderedDict)
                impact_data['post processing'] = postprocessor_data
                with open(json_path, 'w') as json_file_2:
                    json.dump(impact_data, json_file_2, indent=2)
        else:
            post_processing_report = self.impact_function.\
                postprocessor_manager.get_output(
                    self.impact_function.aggregator.aoi_mode)
            keywords['postprocessing_report'] = post_processing_report.to_html(
                suppress_newlines=True)
            self.keyword_io.write_keywords(qgis_impact_layer, keywords)

        # Get tabular information from impact layer
        report = m.Message()
        report.add(LOGO_ELEMENT)
        report.add(m.Heading(self.tr('Analysis Results'), **INFO_STYLE))
        # If JSON Impact Data Exist, use JSON
        json_path = qgis_impact_layer.source()[:-3] + 'json'
        LOGGER.debug('JSON Path %s' % json_path)
        if os.path.exists(json_path):
            impact_template = get_report_template(json_file=json_path)
            impact_report = impact_template.generate_message_report()
            report.add(impact_report)
        else:
            report.add(self.keyword_io.read_keywords(
                qgis_impact_layer, 'impact_summary'))
            # append postprocessing report
            report.add(post_processing_report.to_html())

        # Layer attribution comes last
        report.add(impact_attribution(keywords).to_html(True))

        # Get requested style for impact layer of either kind
        style = safe_impact_layer.get_style_info()
        style_type = safe_impact_layer.get_style_type()

        # Determine styling for QGIS layer
        if safe_impact_layer.is_vector:
            if not style:
                # Set default style if possible
                pass
            elif style_type == 'categorizedSymbol':
                LOGGER.debug('use categorized')
                set_vector_categorized_style(qgis_impact_layer, style)
            elif style_type == 'graduatedSymbol':
                LOGGER.debug('use graduated')
                set_vector_graduated_style(qgis_impact_layer, style)

        elif safe_impact_layer.is_raster:
            if not style:
                qgis_impact_layer.setDrawingStyle("SingleBandPseudoColor")
            else:
                setRasterStyle(qgis_impact_layer, style)

        else:
            message = self.tr(
                'Impact layer %s was neither a raster or a vector layer') % (
                    qgis_impact_layer.source())
            # noinspection PyExceptionInherit
            raise ReadLayerError(message)

        legend = self.iface.legendInterface()

        # Insert the aggregation output above the input aggregation layer
        if self.show_intermediate_layers:
            add_above_layer(
                self.impact_function.aggregator.layer,
                qgis_aggregation)
            legend.setLayerVisible(self.impact_function.aggregator.layer, True)

        if self.hide_exposure_flag:
            # Insert the impact always above the hazard
            add_above_layer(
                qgis_impact_layer,
                qgis_hazard)
        else:
            # Insert the impact above the hazard and the exposure if
            # we don't hide the exposure. See #2899
            add_above_layer(
                qgis_impact_layer,
                qgis_exposure,
                qgis_hazard)

        # In QGIS 2.14.2 and GDAL 1.11.3, if the exposure is in 3857,
        # the impact layer is in 54004, we need to change it. See issue #2790.
        if qgis_exposure.crs().authid() == 'EPSG:3857':
            if qgis_impact_layer.crs().authid() != 'EPSG:3857':
                epsg_3857 = QgsCoordinateReferenceSystem(3857)
                qgis_impact_layer.setCrs(epsg_3857)

        # make sure it is active in the legend - needed since QGIS 2.4
        self.iface.setActiveLayer(qgis_impact_layer)
        # then zoom to it
        if self.zoom_to_impact_flag:
            self.iface.zoomToActiveLayer()
        if self.hide_exposure_flag:
            exposure_layer = self.get_exposure_layer()
            legend.setLayerVisible(exposure_layer, False)

        # Make the layer visible. Might be hidden by default. See #2925
        legend.setLayerVisible(qgis_impact_layer, True)

        # Return text to display in report panel
        return report
Ejemplo n.º 10
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()
        # 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):
            path = str(self.output_directory.text())
            title = str(task_item.text())

            # Its a dict containing files for a scenario
            result = self.run_scenario(value)
            if not result:
                status_item.setText(self.tr('Analysis Fail'))
            else:
                # NOTE(gigih):
                # Usually after analysis is done, the impact layer
                # become the active layer. <--- WRONG
                # noinspection PyUnresolvedReferences
                impact_layer = self.dock.analysis.get_impact_layer()

                # Load impact layer into QGIS
                qgis_layer = read_impact_layer(impact_layer)
                QgsMapLayerRegistry.instance().addMapLayer(
                    qgis_layer, addToLegend=False)

                # noinspection PyBroadException
                try:
                    status_item.setText(self.tr('Analysis Ok'))
                    self.create_pdf(
                        title, path, qgis_layer, count, index)
                    status_item.setText(self.tr('Report Ok'))
                except Exception:  # pylint: disable=W0703
                    LOGGER.exception('Unable to render map: "%s"' % value)
                    status_item.setText(self.tr('Report Failed'))
                    result = False
        else:
            LOGGER.exception('Data type not supported: "%s"' % value)
            result = False

        self.disable_busy_cursor()
        return result
Ejemplo n.º 11
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()
        # 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):
            path = str(self.output_directory.text())
            title = str(task_item.text())

            # Its a dict containing files for a scenario
            result = self.run_scenario(value)
            if not result:
                status_item.setText(self.tr('Analysis Fail'))
            else:
                # NOTE(gigih):
                # Usually after analysis is done, the impact layer
                # become the active layer. <--- WRONG
                # noinspection PyUnresolvedReferences
                impact_layer = self.dock.analysis.impact_layer

                # Load impact layer into QGIS
                qgis_layer = read_impact_layer(impact_layer)
                QgsMapLayerRegistry.instance().addMapLayer(
                    qgis_layer, addToLegend=False)

                # noinspection PyBroadException
                try:
                    status_item.setText(self.tr('Analysis Ok'))
                    self.create_pdf(
                        title, path, qgis_layer, count, index)
                    status_item.setText(self.tr('Report Ok'))
                except Exception:  # pylint: disable=W0703
                    LOGGER.exception('Unable to render map: "%s"' % value)
                    status_item.setText(self.tr('Report Failed'))
                    result = False
        else:
            LOGGER.exception('Data type not supported: "%s"' % value)
            result = False

        self.disable_busy_cursor()
        return result
Ejemplo n.º 12
0
    def show_results(self):
        """Helper function for slot activated when the process is done.

        .. versionchanged:: 3.4 - removed parameters.

        .. note:: If you update this function, please report your change to
            safe.gui.widgets.dock.show_results too.

        :returns: Provides a report for writing to the dock.
        :rtype: str
        """
        qgis_exposure = self.impact_function.exposure.qgis_layer()
        qgis_hazard = self.impact_function.hazard.qgis_layer()
        qgis_aggregation = self.impact_function.aggregation.qgis_layer()

        safe_impact_layer = self.impact_function.impact
        qgis_impact_layer = read_impact_layer(safe_impact_layer)

        keywords = self.keyword_io.read_keywords(qgis_impact_layer)
        json_path = os.path.splitext(qgis_impact_layer.source())[0] + '.json'

        # write postprocessing report to keyword
        postprocessor_data = self.impact_function.postprocessor_manager.\
            get_json_data(self.impact_function.aggregator.aoi_mode)
        post_processing_report = m.Message()
        if os.path.exists(json_path):
            with open(json_path) as json_file:
                impact_data = json.load(json_file,
                                        object_pairs_hook=OrderedDict)
                impact_data['post processing'] = postprocessor_data
                write_json(impact_data, json_path)
        else:
            post_processing_report = self.impact_function.\
                postprocessor_manager.get_output(
                    self.impact_function.aggregator.aoi_mode)
            keywords['postprocessing_report'] = post_processing_report.to_html(
                suppress_newlines=True)
            self.keyword_io.write_keywords(qgis_impact_layer, keywords)

        # Get tabular information from impact layer
        report = m.Message()
        report.add(LOGO_ELEMENT)
        report.add(m.Heading(self.tr('Analysis Results'), **INFO_STYLE))
        # If JSON Impact Data Exist, use JSON
        json_path = qgis_impact_layer.source()[:-3] + 'json'
        LOGGER.debug('JSON Path %s' % json_path)
        if os.path.exists(json_path):
            impact_template = get_report_template(json_file=json_path)
            impact_report = impact_template.generate_message_report()
            report.add(impact_report)
        else:
            report.add(
                self.keyword_io.read_keywords(qgis_impact_layer,
                                              'impact_summary'))
            # append postprocessing report
            report.add(post_processing_report.to_html())

        # Layer attribution comes last
        report.add(impact_attribution(keywords).to_html(True))

        # Get requested style for impact layer of either kind
        style = safe_impact_layer.get_style_info()
        style_type = safe_impact_layer.get_style_type()

        # Determine styling for QGIS layer
        if safe_impact_layer.is_vector:
            if not style:
                # Set default style if possible
                pass
            elif style_type == 'categorizedSymbol':
                LOGGER.debug('use categorized')
                set_vector_categorized_style(qgis_impact_layer, style)
            elif style_type == 'graduatedSymbol':
                LOGGER.debug('use graduated')
                set_vector_graduated_style(qgis_impact_layer, style)

        elif safe_impact_layer.is_raster:
            if not style:
                qgis_impact_layer.setDrawingStyle("SingleBandPseudoColor")
            else:
                setRasterStyle(qgis_impact_layer, style)

        else:
            message = self.tr(
                'Impact layer %s was neither a raster or a vector layer') % (
                    qgis_impact_layer.source())
            # noinspection PyExceptionInherit
            raise ReadLayerError(message)

        legend = self.iface.legendInterface()

        # Insert the aggregation output above the input aggregation layer
        if self.show_intermediate_layers:
            add_above_layer(self.impact_function.aggregator.layer,
                            qgis_aggregation)
            legend.setLayerVisible(self.impact_function.aggregator.layer, True)

        if self.hide_exposure_flag:
            # Insert the impact always above the hazard
            add_above_layer(qgis_impact_layer, qgis_hazard)
        else:
            # Insert the impact above the hazard and the exposure if
            # we don't hide the exposure. See #2899
            add_above_layer(qgis_impact_layer, qgis_exposure, qgis_hazard)

        # In QGIS 2.14.2 and GDAL 1.11.3, if the exposure is in 3857,
        # the impact layer is in 54004, we need to change it. See issue #2790.
        if qgis_exposure.crs().authid() == 'EPSG:3857':
            if qgis_impact_layer.crs().authid() != 'EPSG:3857':
                epsg_3857 = QgsCoordinateReferenceSystem(3857)
                qgis_impact_layer.setCrs(epsg_3857)

        # make sure it is active in the legend - needed since QGIS 2.4
        self.iface.setActiveLayer(qgis_impact_layer)
        # then zoom to it
        if self.zoom_to_impact_flag:
            self.iface.zoomToActiveLayer()
        if self.hide_exposure_flag:
            exposure_layer = self.get_exposure_layer()
            legend.setLayerVisible(exposure_layer, False)

        # Make the layer visible. Might be hidden by default. See #2925
        legend.setLayerVisible(qgis_impact_layer, True)

        # Return text to display in report panel
        return report