Пример #1
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
Пример #2
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
Пример #3
0
    def print_impact_table(self, output_path):
        """Pint summary from impact layer to PDF.

        ..note:: The order of the report:
            1. Summary table
            2. Aggregation table
            3. Attribution table

        :param output_path: Output path.
        :type output_path: str

        :return: Path to generated pdf file.
        :rtype: str

        :raises: None
        """
        keywords = self._keyword_io.read_keywords(self.layer)

        if output_path is None:
            output_path = unique_filename(suffix='.pdf', dir=temp_dir())

        try:
            impact_template = get_report_template(self.layer.source())
            summary_table = impact_template.generate_html_report()
        except:
            summary_table = keywords.get('impact_summary', None)
        full_table = keywords.get('impact_table', None)
        aggregation_table = keywords.get('postprocessing_report', None)
        attribution_table = impact_attribution(keywords)

        # (AG) We will not use impact_table as most of the IF use that as:
        # impact_table = impact_summary + some information intended to be
        # shown on screen (see FloodOsmBuilding)
        # Unless the impact_summary is None, we will use impact_table as the
        # alternative
        html = m.Brand().to_html()
        html += m.Heading(tr('Analysis Results'), **INFO_STYLE).to_html()
        if summary_table is None:
            html += full_table
        else:
            html += summary_table

        if aggregation_table is not None:
            html += aggregation_table

        if attribution_table is not None:
            html += attribution_table.to_html()

        html = html_header() + html + html_footer()

        # Print HTML using composition
        # For QGIS < 2.4 compatibility
        # QgsMapSettings is added in 2.4
        if qgis_version() < 20400:
            map_settings = QgsMapRenderer()
        else:
            map_settings = QgsMapSettings()

        # A4 Portrait
        # TODO: Will break when we try to use larger print layouts TS
        paper_width = 210
        paper_height = 297

        # noinspection PyCallingNonCallable
        composition = QgsComposition(map_settings)
        # noinspection PyUnresolvedReferences
        composition.setPlotStyle(QgsComposition.Print)
        composition.setPaperSize(paper_width, paper_height)
        composition.setPrintResolution(300)

        # Add HTML Frame
        # noinspection PyCallingNonCallable
        html_item = QgsComposerHtml(composition, False)
        margin_left = 10
        margin_top = 10

        # noinspection PyCallingNonCallable
        html_frame = QgsComposerFrame(
            composition,
            html_item,
            margin_left,
            margin_top,
            paper_width - 2 * margin_left,
            paper_height - 2 * margin_top)
        html_item.addFrame(html_frame)

        # Set HTML
        # From QGIS 2.6, we can set composer HTML with manual HTML
        if qgis_version() < 20600:
            html_path = unique_filename(
                prefix='report', suffix='.html', dir=temp_dir())
            html_to_file(html, file_path=html_path)
            html_url = QUrl.fromLocalFile(html_path)
            html_item.setUrl(html_url)
        else:
            # noinspection PyUnresolvedReferences
            html_item.setContentMode(QgsComposerHtml.ManualHtml)
            # noinspection PyUnresolvedReferences
            html_item.setResizeMode(QgsComposerHtml.RepeatUntilFinished)
            html_item.setHtml(html)
            # RMN: This line below breaks in InaSAFE Headless after one
            # successful call. This is because the function is not
            # thread safe. Can't do anything about this, so avoid calling this
            # function in multithreaded way.
            html_item.loadHtml()

        composition.exportAsPDF(output_path)
        return output_path
Пример #4
0
    def show_results(self, qgis_impact_layer, engine_impact_layer):
        """Helper function for slot activated when the process is done.

        .. note:: Adapted from the dock

        :param qgis_impact_layer: A QGIS layer representing the impact.
        :type qgis_impact_layer: QgsMapLayer, QgsVectorLayer, QgsRasterLayer

        :param engine_impact_layer: A safe_layer representing the impact.
        :type engine_impact_layer: ReadLayer

        :returns: Provides a report for writing to the dock.
        :rtype: str
        """
        keywords = self.keyword_io.read_keywords(qgis_impact_layer)
        json_path = os.path.splitext(qgis_impact_layer.source())[0] + '.json'

        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:
            # write postprocessing report to keyword
            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))
        try:
            impact_template = get_report_template(
                impact_layer_path=qgis_impact_layer.source())
            impact_report = impact_template.generate_message_report()
            report.add(impact_report)
        except MissingImpactReport:
            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 = engine_impact_layer.get_style_info()
        style_type = engine_impact_layer.get_style_type()

        # Determine styling for QGIS layer
        if engine_impact_layer.is_vector:
            LOGGER.debug('myEngineImpactLayer.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 engine_impact_layer.is_raster:
            LOGGER.debug('myEngineImpactLayer.is_raster')
            if not style:
                qgis_impact_layer.setDrawingStyle("SingleBandPseudoColor")
                # qgis_impact_layer.setColorShadingAlgorithm(
                #    QgsRasterLayer.PseudoColorShader)
            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)

        # Add layers to QGIS
        layers_to_add = []
        if self.show_intermediate_layers:
            layers_to_add.append(self.impact_function.aggregator.layer)
        layers_to_add.append(qgis_impact_layer)
        # noinspection PyArgumentList
        QgsMapLayerRegistry.instance().addMapLayers(layers_to_add)
        # 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.impact_function.exposure.qgis_layer()
            legend = self.iface.legendInterface()
            legend.setLayerVisible(exposure_layer, False)

        # Return text to display in report panel
        return report