Exemple #1
0
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, You can choose a exposure '
                   'layer from the list of layers that have been loaded to QGIS and '
                   'that matches with the geometry and exposure type you set in the '
                   'previous step').format(step_name=self.step_name)))
        return message
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, you will be able to define '
                   'field mappings to use for demographic breakdowns of your '
                   'analysis results.').format(step_name=self.step_name)))
        message.add(field_mapping_help_content())
        return message
    def help_content(self):
        """Return the content of help for this step wizard.

        We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(m.Paragraph(tr(
            'In this wizard step: {step_name}, you will know that your '
            'exposure and hazard layer do not intersect with your aggregation '
            'layer. You can not go forward and you need to change the layer '
            'to run an analysis.'
        ).format(step_name=self.step_name)))
        return message
Exemple #4
0
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, you will be able to set the '
                   'classification that you will use per exposure type. You can also '
                   'set the threshold or value map for each classification.').
                format(step_name=self.step_name)))
        return message
Exemple #5
0
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, you will be able to set the '
                   'unit of the layer that is being assigned in this wizard. This '
                   'only applies for continuous layer.').format(
                       step_name=self.step_name)))
        return message
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, You can choose a hazard layer '
                   'from the list of layers from local disk or postgres database '
                   'that matches with the geometry and hazard type you set in the '
                   'previous step').format(step_name=self.step_name)))
        return message
Exemple #7
0
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, you can choose where your '
                   'aggregation layer come from. The option for choosing aggregation '
                   'layer from QGIS can not be chosen if there is no aggregation '
                   'layer in QGIS.').format(step_name=self.step_name)))
        return message
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, you will see the summary of '
                   'the analysis that you have set up from the previous steps. You '
                   'can click run button to run the analysis.').format(
                       step_name=self.step_name)))
        return message
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, you will be able to map the '
                   'value in the field (in the left panel) to a group in the right '
                   'panel. You can do this by drag the value and drop it to the '
                   'preferred group.').format(step_name=self.step_name)))
        return message
Exemple #10
0
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(m.Paragraph(tr(
            'In this wizard step: {step_name}, you will be able to '
            'set a field that corresponded with a InaSAFE field '
            'concept. It also allows you to set a default value for all '
            'feature if you do not want to use any field').format(
            step_name=self.step_name)))
        return message
Exemple #11
0
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, you will be able to set the '
                   'purpose of the layer. We have 3 options: hazard, exposure, '
                   'and aggregation layer purpose.'
                   '').format(step_name=self.step_name)))
        return message
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name}, you will be able to '
                   'set a value that corresponded with a InaSAFE field '
                   'concept as default value.').format(
                       step_name=self.step_name)))
        return message
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 3.2.2

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()

    message.add(
        m.Paragraph(
            tr('To start report generation you need to click on the Print... '
               'button in the buttons area. This will open the Impact report '
               'dialog which has three main areas.')))

    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            m.ImportantText(tr('Area to print')),
            tr(' - There are two options available. Choose Current extent if '
               'current canvas extent represents necessary area. Analysis '
               'extent will set extent of the report map to impact layer '
               'extent.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Template to use')),
            tr(' - Here you can select desired template for your report. All '
               'templates bundled with InaSAFE are available here, plus '
               'templates from user-defined template directory (see Options '
               'for information how to set templates directory). It is also '
               'possible to select custom template from any location: just '
               'activate radiobutton under combobox and provide path to template '
               'using the "..." button.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Buttons area')),
            tr(' - In this area you will find buttons to open the report as '
               'a PDF or in the QGIS print composer. You can also get help by '
               'clicking on the help button or using the close button to close '
               'the print dialog.')))
    message.add(bullets)

    return message
Exemple #14
0
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(m.Paragraph(tr(
            'In this wizard step: {step_name}, you will see the summary of '
            'the analysis that you have run. You can get your PDF report or '
            'show the report in the web browser by clicking the <b>Generate '
            'PDF</b> and <b>Open in web browser</b> respectively. You can '
            'also click the <b>Finish</b> button to end the wizard session.'
        ).format(step_name=self.step_name)))
        return message
Exemple #15
0
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 3.2.3

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    link = m.Link('https://petajakarta.org', 'PetaJakarta.org')
    body = m.Paragraph(
        tr('This tool will fetch current flood data for Jakarta from '), link)
    tips = m.BulletedList()
    tips.add(
        tr('Check the output directory is correct. Note that the saved '
           'dataset will be called jakarta_flood.shp (and associated files).'))
    tips.add(
        tr('If you wish you can specify a prefix to '
           'add in front of this default name. For example using a prefix '
           'of \'foo-\' will cause the downloaded files to be saved as e.g. '
           '\'foo-rw-jakarta-flood.shp\'. Note that the only allowed prefix '
           'characters are A-Z, a-z, 0-9 and the characters \'-\' and \'_\'. '
           'You can leave this blank if you prefer.'))
    tips.add(
        tr('If a dataset already exists in the output directory it will be '
           'overwritten if the "overwrite existing files" checkbox is ticked.')
    )
    tips.add(
        tr('If the "include date/time in output filename" option is ticked, '
           'the filename will be prefixed with a time stamp e.g. '
           '\'foo-22-Mar-2015-08-01-2015-rw-jakarta-flood.shp\' where the date '
           'timestamp is in the form DD-MMM-YYYY.'))
    tips.add(
        tr('This tool requires a working internet connection and fetching '
           'data will consume your bandwidth.'))
    tips.add(
        m.Link('https://petajakarta.org/banjir/en/data/',
               text=tr(
                   'Downloaded data is copyright the PetaJakarta contributors'
                   ' (click for more info).')))
    message.add(body)
    message.add(tips)
    return message
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(m.Paragraph(tr(
            'In this wizard step: {step_name}, you will be able to set the '
            'type of your layer based on the purpose that you have set in the '
            'previous step (if you choose hazard or exposure purpose). In '
            'this step, there is list of exposure / hazard type that you can '
            'select to specify your layer purpose type.'
        ).format(step_name=self.step_name)))
        return message
Exemple #17
0
    def help_content(self):
        """Return the content of help for this step wizard.

        We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(
            m.Paragraph(
                tr('In this wizard step: {step_name} you will be allowed to specify '
                   'which geographical region should be used for your analysis. '
                   'There are a number of different modes that can be used which are '
                   'described below:').format(step_name=self.step_name)))
        message.add(extent_mode_content())
        return message
Exemple #18
0
    def help_content(self):
        """Return the content of help for this step wizard.

            We only needs to re-implement this method in each wizard step.

        :returns: A message object contains help.
        :rtype: m.Message
        """
        message = m.Message()
        message.add(m.Paragraph(tr(
            'In this wizard step: {step_name}, there is a grid that shows all '
            'possible combination for hazard and exposure that can be run in '
            'InaSAFE. You can select a grid cell where your intended exposure '
            'and hazard intersect. This will help you to choose the '
            'layer that is suitable for the analysis. You can only '
            'select the green grid cell. The grey color indicates that the '
            'combination is not supported by InaSAFE.'
            '').format(step_name=self.step_name)))
        return message
Exemple #19
0
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 3.2.2

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """

    message = m.Message()
    paragraph = m.Paragraph(
        m.Image(
            'file:///%s/img/screenshots/'
            'shakemap-converter-screenshot.png' % resources_path()),
        style_class='text-center'
    )
    message.add(paragraph)
    body = tr(
        'This tool will convert an earthquake \'shakemap\' that is in '
        'grid xml format into a GeoTIFF file. The imported file can be used '
        'in InaSAFE as an input for impact functions that require an '
        'earthquake layer.  To use this tool effectively:')
    message.add(body)
    tips = m.BulletedList()
    tips.add(tr(
        'Select a grid.xml for the input layer.'))
    tips.add(tr(
        'Choose where to write the output layer to.'
    ))
    tips.add(tr(
        'Choose the interpolation algorithm that should be used when '
        'converting the xml grid to a raster. If unsure keep the default.'
    ))
    tips.add(tr(
        'If you want to obtain shake data you can get download it free from '
        'the USGS shakemap site: '
        'http://earthquake.usgs.gov/earthquakes/shakemap/list.php?y=2013'))

    message.add(tips)
    return message
def missing_keyword_message(sender, missing_keyword_exception):
    """Display an error when there is missing keyword.

    :param sender: The sender.
    :type sender: object

    :param missing_keyword_exception: A KeywordNotFoundError exception.
    :type missing_keyword_exception: KeywordNotFoundError

    """
    warning_heading = m.Heading(
        tr('Missing Keyword'), **WARNING_STYLE)
    warning_message = tr(
        'There is missing keyword that needed for this analysis.')
    detail_heading = m.Heading(
        tr('Detail'), **DETAILS_STYLE)
    suggestion_heading = m.Heading(
        tr('Suggestion'), **DETAILS_STYLE)
    detail = tr(
        'The layer <b>%s</b> is missing the keyword <i>%s</i>.' % (
            missing_keyword_exception.layer_name,
            missing_keyword_exception.keyword
        )
    )
    suggestion = m.Paragraph(
            tr('Please use the keyword wizard to update the keywords. You '
               'can open the wizard by clicking on the '),
            m.Image(
                'file:///%s/img/icons/'
                'show-keyword-wizard.svg' % resources_path(),
                **SMALL_ICON_STYLE),
            tr(
                ' icon in the toolbar.'))

    message = m.Message()
    message.add(warning_heading)
    message.add(warning_message)
    message.add(detail_heading)
    message.add(detail)
    message.add(suggestion_heading)
    message.add(suggestion)
    send_static_message(sender, message)
Exemple #21
0
def show_no_keywords_message(sender):
    """Show a message indicating that no keywords are defined.

    .. note:: The print button will be disabled if this method is called.
    """
    LOGGER.debug('Showing No Keywords Message')
    message = generate_input_error_message(
        tr('Layer keywords missing:'),
        m.Paragraph(
            tr('No keywords have been defined for this layer yet or there is '
               'an issue with the currently defined keywords and they need '
               'to be reviewed. If you wish to use this layer as an '
               'exposure, hazard, or aggregation layer in an analysis, '
               'please use the keyword wizard to update the keywords. You '
               'can open the wizard by clicking on the '),
            m.Image(
                'file:///%s/img/icons/'
                'show-keyword-wizard.svg' % resources_path(),
                **SMALL_ICON_STYLE), tr(' icon in the toolbar.')))
    send_static_message(sender, message)
Exemple #22
0
    def open_as_pdf(self):
        """Print the selected report as a PDF product.

        .. versionadded: 4.3.0
        """
        # Get output path from datastore
        report_urls_dict = report_urls(self.impact_function)

        # get report urls for each product tag as list
        for key, value in list(report_urls_dict.items()):
            report_urls_dict[key] = list(value.values())

        if self.dock:
            # create message to user
            status = m.Message(
                m.Heading(self.dock.tr('Map Creator'), **INFO_STYLE),
                m.Paragraph(
                    self.dock.
                    tr('Your PDF was created....opening using the default PDF '
                       'viewer on your system.')),
                m.ImportantText(
                    self.dock.tr('The generated pdfs were saved '
                                 'as:')))

            for path in report_urls_dict.get(pdf_product_tag['key'], []):
                status.add(m.Paragraph(path))

            status.add(
                m.Paragraph(
                    m.ImportantText(
                        self.dock.tr('The generated htmls were saved as:'))))

            for path in report_urls_dict.get(html_product_tag['key'], []):
                status.add(m.Paragraph(path))

            status.add(
                m.Paragraph(
                    m.ImportantText(
                        self.dock.tr('The generated qpts were saved as:'))))

            for path in report_urls_dict.get(qpt_product_tag['key'], []):
                status.add(m.Paragraph(path))

            send_static_message(self.dock, status)

        for path in report_urls_dict.get(pdf_product_tag['key'], []):
            # noinspection PyCallByClass,PyTypeChecker,PyTypeChecker
            QtGui.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(path))
def getting_started_message():
    """Generate a message for initial application state.

    :returns: Information for the user on how to get started.
    :rtype: safe.messaging.Message
    """
    message = m.Message()
    message.add(LOGO_ELEMENT)
    message.add(m.Heading(tr('Getting started'), **INFO_STYLE))
    notes = m.Paragraph(
        tr(
            'These are the minimum steps you need to follow in order '
            'to use InaSAFE:'))
    message.add(notes)
    basics_list = m.NumberedList()
    basics_list.add(m.Paragraph(
        tr('Add at least one '),
        m.ImportantText(tr('hazard'), **KEYWORD_STYLE),
        tr(' layer (e.g. earthquake MMI) to QGIS.')))
    basics_list.add(m.Paragraph(
        tr('Add at least one '),
        m.ImportantText(tr('exposure'), **KEYWORD_STYLE),
        tr(' layer (e.g. structures) to QGIS.')))
    basics_list.add(m.Paragraph(
        tr(
            'Make sure you have defined keywords for your hazard and '
            'exposure layers. You can do this using the '
            'keywords creation wizard '),
        m.Image(
            'file:///%s/img/icons/show-keyword-wizard.svg' %
            (resources_path()), **SMALL_ICON_STYLE),
        tr(' in the toolbar.')))
    basics_list.add(m.Paragraph(
        tr('Click on the '),
        m.ImportantText(tr('Run'), **KEYWORD_STYLE),
        tr(' button below.')))
    message.add(basics_list)

    message.add(m.Heading(tr('Limitations'), **WARNING_STYLE))
    caveat_list = m.NumberedList()
    for limitation in limitations():
        caveat_list.add(limitation)
    message.add(caveat_list)

    message.add(m.Heading(tr('Disclaimer'), **WARNING_STYLE))
    message.add(m.Paragraph(disclaimer()))

    return message
Exemple #24
0
def show_keywords_need_review_message(sender, message=None):
    """Show a message keywords are not adequate to run an analysis.

    .. versionadded: 4.0

    :param message: Additional message to display.
    :type message: str

    .. note:: The print button will be disabled if this method is called.
    """
    LOGGER.debug('Showing incorrect keywords for v4 message')
    message = generate_input_error_message(
        tr('Layer Keywords Outdated:'),
        m.Paragraph(
            tr('Please update the keywords for your layers and then '
               'try to run the analysis again. Use the keyword wizard '),
            m.Image(
                'file:///%s/img/icons/'
                'show-keyword-wizard.svg' % resources_path(),
                **SMALL_ICON_STYLE),
            tr(' icon in the toolbar to update your layer\'s keywords.'),
            message))
    send_static_message(sender, message)
Exemple #25
0
def show_keyword_version_message(sender, keyword_version, inasafe_version):
    """Show a message indicating that the keywords version is mismatch

    .. versionadded: 3.2

    :param sender: Sender of the message signal. Default to Any object.
    :type sender: object

    :param keyword_version: The version of the layer's keywords
    :type keyword_version: str

    :param inasafe_version: The version of the InaSAFE
    :type inasafe_version: str

    .. note:: The print button will be disabled if this method is called.
    """
    LOGGER.debug('Showing Mismatch Version Message')
    message = generate_input_error_message(
        tr('Layer Keyword\'s Version Mismatch:'),
        m.Paragraph(
            tr(
                'Your layer\'s keyword\'s version ({layer_version}) does not '
                'match with your InaSAFE version ({inasafe_version}). If you '
                'wish to use it as an exposure, hazard, or aggregation layer '
                'in an analysis, please use the keyword wizard to update the '
                'keywords. You can open the wizard by clicking on '
                'the ').format(
                layer_version=keyword_version,
                inasafe_version=inasafe_version),
            m.Image(
                'file:///%s/img/icons/'
                'show-keyword-wizard.svg' % resources_path(),
                **SMALL_ICON_STYLE),
            tr(
                ' icon in the toolbar.'))
    )
    send_static_message(sender, message)
Exemple #26
0
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 4.1.0

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    message.add(
        m.Paragraph(
            tr('This section of the help documentation is intended for advanced '
               'users who want to modify the internals of InaSAFE. It assumes that '
               'you have basic coding skills. All examples are in python unless '
               'otherwise stated.')))
    message.add(m.Heading(tr('Defining a new hazard type'),
                          **SUBSECTION_STYLE))
    message.add(m.Heading(tr('Background'), **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        tr('In the previous versions of InaSAFE, we spent a lot of effort '
           'building one impact function per hazard/exposure combination (and '
           'sometimes multiple impact functions per combination). In our new '
           'architecture, we try to deal with everything in the same way - by '
           'following a standardized process of converting the hazard dataset '
           'into a classified polygon layer and then calculating the impacted '
           'and affected areas using a standard work-flow. A simplified version '
           'of this work-flow is described in illustration 1.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Because of this change, you will no longer see an impact function '
           'selector in the dock widget and there are no longer any \'impact '
           'function options\' as we had in previous versions of InaSAFE. In '
           'the new system, almost all configuration is managed through '
           'metadata (created using the keywords wizard).'))

    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Also, in all versions prior to Version 4.0, we made heavy use of '
           'interpolation in order to determine whether buildings or other '
           'exposure layers are impacted. While this is a commonly used '
           'technique in GIS, it often leads to non - intuitive looking '
           'reports. Under our new architecture, we always use geometric '
           'overlay operations to make a determination whether an exposure '
           'feature is affected or not. The implication of this is that we '
           'produce intuitive and easily verifiable impact layers. You can '
           'see an example in Illustration 2.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Stepping away from the two previously mentioned paradigms allows '
           'us to simply add new hazard types to the metadata driven impact '
           'function by adding new metadata types to the InaSAFE sources. '
           'In the next chapter we show you how this was achieved and how '
           'it can be repeated for further hazards using the example of '
           'tropical cyclones.'))
    message.add(paragraph)
    message.add(m.Heading(tr('Adding a new hazard'), **BLUE_CHAPTER_STYLE))
    link = m.Link('https://github.com/inasafe/inasafe/pull/3539/files',
                  tr('Pull Request #3539'))
    paragraph = m.Paragraph(
        tr('The whole work needed can be looked at in '), link,
        tr('. Please bear in mind that the paths of the files are now '
           'safe/definitions/xxx.py and not safe/definitionsv4/xxx.py since '
           'v4 is the default codebase. In the next sections we will show '
           'each file that needs to be extended in order to add a new hazard '
           'type.'))
    message.add(paragraph)

    # Setting up units

    message.add(
        m.Heading(tr('safe/definitions/units.py'), **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        tr('If you are adding an hazard that uses units that are not yet known '
           'to InaSAFE, you need to define them in units.py'))
    message.add(paragraph)
    paragraph = m.PreformattedText(
        _get_definition_from_module(units, 'unit_kilometres_per_hour'))
    message.add(paragraph)

    # Setting up style

    message.add(m.Heading('safe/definitions/colors.py', **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        'If you are adding an hazard that has more classes than any other '
        'hazards you’ll need to add additional colors for the additional '
        'classes in colors.py. You might also define other colors if you '
        'don\'t want to use the standard colors. For the sake of homogeneous '
        'map reports, this addition should not be taken lightly.')
    message.add(paragraph)
    # Don't translate this
    paragraph = m.PreformattedText('very_dark_red = Qcolor(\'#710017\')')
    message.add(paragraph)

    # Setting up hazard classification

    message.add(
        m.Heading('safe/definitions/hazard_classifications.py',
                  **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        tr('Add the classifications you want to make available for your new '
           'hazard type. You can add as many classes as you want in the '
           'classes list.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Also, a classification can support multiple units so you don\'t '
           'have to define different classifications just to have the same '
           'classification in two or more different units. These are defined '
           'in the multiple_units attribute of the classification.'))
    message.add(paragraph)

    paragraph = m.PreformattedText(
        _get_definition_from_module(hazard_classifications,
                                    'cyclone_au_bom_hazard_classes'))
    message.add(paragraph)

    # Setting up wizard questions

    message.add(
        m.Heading('safe/gui/tools/wizard/wizard_strings.py',
                  **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(tr('Define the questions for the wizard:'))
    message.add(paragraph)
    # don not translate
    message.add(
        m.PreformattedText(
            'cyclone_kilometres_per_hour_question = tr(\'wind speed in km/h\')'
        ))
    message.add(
        m.PreformattedText(
            'cyclone_miles_per_hour_question = tr(\'wind speed in mph\')'))
    message.add(
        m.PreformattedText(
            'cyclone_knots_question = tr(\'wind speed in kn\')'))

    # Setting up

    message.add(m.Heading('safe/definitions/hazard.py', **BLUE_CHAPTER_STYLE))
    paragraph = m.Paragraph(
        tr('Finally define new hazard and add it to the hazard_all list:'))
    message.add(paragraph)
    paragraph = m.PreformattedText(
        _get_definition_from_module(hazard, 'hazard_cyclone'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Finally define new hazard and add it to the hazard_all list:'))
    message.add(paragraph)
    paragraph = m.PreformattedText(
        _get_definition_from_module(hazard, 'hazard_all'))
    message.add(paragraph)
    return message
Exemple #27
0
    def run(self):
        """Run any post processors requested by the impact function.
        """
        try:
            requested_postprocessors = self.function_parameters[
                'postprocessors']
            postprocessors = get_postprocessors(requested_postprocessors)
        except (TypeError, KeyError):
            # TypeError is for when function_parameters is none
            # KeyError is for when ['postprocessors'] is unavailable
            postprocessors = {}

        feature_names_attribute = self.aggregator.attributes[
            self.aggregator.get_default_keyword('AGGR_ATTR_KEY')]
        if feature_names_attribute is None:
            self.attribute_title = self.tr('Aggregation unit')
        else:
            self.attribute_title = feature_names_attribute

        name_filed_index = self.aggregator.layer.fieldNameIndex(
            self.attribute_title)
        sum_field_index = self.aggregator.layer.fieldNameIndex(
            self._sum_field_name())

        user_defined_female_ratio = False
        female_ratio_field_index = None
        female_ratio = None
        user_defined_age_ratios = False
        youth_ratio_field_index = None
        youth_ratio = None
        adult_ratio_field_index = None
        adult_ratio = None
        elderly_ratio_field_index = None
        elderly_ratio = None

        if 'Gender' in postprocessors:
            # look if we need to look for a variable female ratio in a layer
            try:
                female_ratio_field = self.aggregator.attributes[
                    self.aggregator.get_default_keyword(
                        'FEMALE_RATIO_ATTR_KEY')]
                female_ratio_field_index = \
                    self.aggregator.layer.fieldNameIndex(female_ratio_field)

                # something went wrong finding the female ratio field,
                # use defaults from below except block
                if female_ratio_field_index == -1:
                    raise KeyError

                user_defined_female_ratio = True

            except KeyError:
                try:
                    female_ratio = self.keyword_io.read_keywords(
                        self.aggregator.layer,
                        self.aggregator.get_default_keyword(
                            'FEMALE_RATIO_KEY'))
                except KeywordNotFoundError:
                    female_ratio = \
                        self.aggregator.get_default_keyword('FEMALE_RATIO')

        if 'Age' in postprocessors:
            # look if we need to look for a variable age ratio in a layer
            try:
                youth_ratio_field = self.aggregator.attributes[
                    self.aggregator.get_default_keyword(
                        'YOUTH_RATIO_ATTR_KEY')]
                youth_ratio_field_index = \
                    self.aggregator.layer.fieldNameIndex(youth_ratio_field)
                adult_ratio_field = self.aggregator.attributes[
                    self.aggregator.get_default_keyword(
                        'ADULT_RATIO_ATTR_KEY')]
                adult_ratio_field_index = \
                    self.aggregator.layer.fieldNameIndex(adult_ratio_field)
                elderly_ratio_field = self.aggregator.attributes[
                    self.aggregator.get_default_keyword(
                        'ELDERLY_RATIO_ATTR_KEY')]
                elderly_ratio_field_index = \
                    self.aggregator.layer.fieldNameIndex(elderly_ratio_field)
                # something went wrong finding the youth ratio field,
                # use defaults from below except block
                if (youth_ratio_field_index == -1
                        or adult_ratio_field_index == -1
                        or elderly_ratio_field_index == -1):
                    raise KeyError

                user_defined_age_ratios = True

            except KeyError:
                try:
                    youth_ratio = self.keyword_io.read_keywords(
                        self.aggregator.layer,
                        self.aggregator.get_default_keyword('YOUTH_RATIO_KEY'))
                    adult_ratio = self.keyword_io.read_keywords(
                        self.aggregator.layer,
                        self.aggregator.get_default_keyword('ADULT_RATIO_KEY'))
                    elderly_ratio = self.keyword_io.read_keywords(
                        self.aggregator.layer,
                        self.aggregator.get_default_keyword(
                            'ELDERLY_RATIO_KEY'))

                except KeywordNotFoundError:
                    youth_ratio = \
                        self.aggregator.get_default_keyword('YOUTH_RATIO')
                    adult_ratio = \
                        self.aggregator.get_default_keyword('ADULT_RATIO')
                    elderly_ratio = \
                        self.aggregator.get_default_keyword('ELDERLY_RATIO')

        # iterate zone features
        request = QgsFeatureRequest()
        request.setFlags(QgsFeatureRequest.NoGeometry)
        provider = self.aggregator.layer.dataProvider()
        # start data retrieval: fetch no geometry and all attributes for each
        # feature
        polygon_index = 0
        for feature in provider.getFeatures(request):
            # if a feature has no field called
            if name_filed_index == -1:
                zone_name = str(feature.id())
            else:
                zone_name = feature[name_filed_index]
            if isinstance(zone_name, QPyNullVariant):
                # proper format for i186
                zone_name = tr('Unnamed Area %(feature_id)s') % {
                    'feature_id': str(feature.id())
                }

            # create dictionary of attributes to pass to postprocessor
            general_params = {
                'target_field': self.aggregator.target_field,
                'function_params': self.function_parameters
            }

            impact_total = feature[sum_field_index]
            general_params['impact_total'] = impact_total

            try:
                general_params['impact_attrs'] = (
                    self.aggregator.impact_layer_attributes[polygon_index])
            except IndexError:
                # rasters and attributeless vectors have no attributes
                general_params['impact_attrs'] = None
            for key, value in postprocessors.iteritems():
                parameters = general_params
                user_parameters = self.function_parameters['postprocessors'][
                    key]
                user_parameters = dict([(user_parameter.name,
                                         user_parameter.value)
                                        for user_parameter in user_parameters])
                try:
                    # user parameters override default parameters
                    parameters.update(user_parameters)
                except KeyError:
                    pass

                if key == 'Gender':
                    if user_defined_female_ratio:
                        female_ratio = feature[female_ratio_field_index]
                        if female_ratio is None:
                            female_ratio = self.aggregator.defaults[
                                'FEMALE_RATIO']
                            LOGGER.warning('Data Driven Female ratio '
                                           'incomplete, using defaults for'
                                           ' aggregation unit'
                                           ' %s' % feature.id)

                    parameters['female_ratio'] = female_ratio

                if key == 'Age':
                    if user_defined_age_ratios:
                        youth_ratio = feature[youth_ratio_field_index]
                        adult_ratio = feature[adult_ratio_field_index]
                        elderly_ratio = feature[elderly_ratio_field_index]
                        if (youth_ratio is None or adult_ratio is None
                                or elderly_ratio is None):
                            LOGGER.debug(
                                '--- only default age ratios used ---')
                            youth_ratio = self.aggregator.defaults[
                                'YOUTH_RATIO']
                            adult_ratio = self.aggregator.defaults[
                                'ADULT_RATIO']
                            elderly_ratio = self.aggregator.defaults[
                                'ELDERLY_RATIO']
                            LOGGER.warning('Data Driven Age ratios '
                                           'incomplete, using defaults for'
                                           ' aggregation unit'
                                           ' %s' % feature.id)

                    parameters['youth_ratio'] = youth_ratio
                    parameters['adult_ratio'] = adult_ratio
                    parameters['elderly_ratio'] = elderly_ratio

                if key == 'BuildingType' or key == 'RoadType':
                    if key == 'BuildingType':
                        key_attribute = self.keyword_io.read_keywords(
                            self.aggregator.exposure_layer,
                            'structure_class_field')
                    elif key == 'RoadType':
                        key_attribute = self.keyword_io.read_keywords(
                            self.aggregator.exposure_layer, 'road_class_field')
                    else:
                        try:
                            key_attribute = self.keyword_io.read_keywords(
                                self.aggregator.exposure_layer,
                                'key_attribute')
                        except KeywordNotFoundError:
                            # use 'type' as default
                            key_attribute = 'type'

                    parameters['key_attribute'] = key_attribute
                    LOGGER.debug('key_attribute: %s', key_attribute)

                    value_map = self.keyword_io.read_keywords(
                        self.aggregator.exposure_layer, 'value_mapping')
                    parameters['value_mapping'] = value_map

                try:
                    value.setup(parameters)
                    value.process()
                    results = value.results()
                    value.clear()
                    if key not in self.output:
                        self.output[key] = []
                    self.output[key].append([zone_name, results])

                except PostProcessorError as e:
                    message = m.Message(
                        m.Heading(self.tr('%s postprocessor problem' % key),
                                  **styles.DETAILS_STYLE),
                        m.Paragraph(self.tr(str(e))))
                    self.error_message = message
            # increment the index
            polygon_index += 1
        self.remove_empty_columns()
        self.remove_empty_lines()
Exemple #28
0
    def _generate_tables(self, aoi_mode=True):
        """Parses the postprocessing output as one table per postprocessor.

        TODO: This should rather return json and then have a helper method to
        make html from the JSON.

        :param aoi_mode: adds a Total in aggregation areas
        row to the calculated table
        :type aoi_mode: bool

        :returns: The html.
        :rtype: str
        """
        message = m.Message()

        for processor, results_list in self.output.iteritems():
            self.current_output_postprocessor = processor
            # results_list is for example:
            # [
            # (PyQt4.QtCore.QString(u'Entire area'), OrderedDict([
            #        (u'Total', {'value': 977536, 'metadata': {}}),
            #        (u'Female population', {'value': 508319, 'metadata': {}}),
            #        (u'Weekly hygiene packs', {'value': 403453, 'metadata': {
            #         'description': 'Females hygiene packs for weekly use'}})
            #    ]))
            # ]
            # sorting using the first indicator of a postprocessor
            sorted_results = sorted(results_list,
                                    key=self._sort_no_data,
                                    reverse=True)

            # init table
            has_no_data = False
            table = m.Table(style_class='table table-condensed table-striped')
            name = get_postprocessor_human_name(processor).lower()
            translated_name = tr(name)

            if name == 'building type':
                table.caption = tr('Closed buildings')
            elif name == 'road type':
                table.caption = tr('Closed roads')
            elif name == 'people':
                table.caption = tr('Affected people')

            # Dirty hack to make "evacuated" come out in the report.
            # Currently only MinimumNeeds that calculate from evacuation
            # percentage.
            if processor == 'MinimumNeeds':
                if 'evacuation_percentage' in self.function_parameters.keys():
                    table.caption = tr(
                        'Detailed %s report '
                        '(for people needing evacuation)') % translated_name
                else:
                    table.caption = tr('Detailed %s report '
                                       '(affected people)') % translated_name

            if processor in ['Gender', 'Age']:
                table.caption = tr('Detailed %s report '
                                   '(affected people)') % translated_name

            empty_table = not sorted_results[0][1]
            if empty_table:
                # Due to an error? The table is empty.
                message.add(table)
                message.add(
                    m.EmphasizedText(
                        tr('Could not compute the %s report.') %
                        translated_name))
                continue

            header = m.Row()
            header.add(str(self.attribute_title).capitalize())
            for calculation_name in sorted_results[0][1]:
                header.add(self.tr(calculation_name))
            table.add(header)

            # used to calculate the totals row as per issue #690
            postprocessor_totals = OrderedDict()

            null_index = 0  # counting how many null value in the data
            for zone_name, calc in sorted_results:
                if isinstance(zone_name, QPyNullVariant):
                    # I have made sure that the zone_name won't be Null in
                    # run method. But just in case there is something wrong.
                    zone_name = tr('Unnamed Area %s' % null_index)
                    null_index += 1
                if name == 'road type':
                    # We add the unit 'meter' as we are counting roads.
                    # proper format for i186
                    zone_name = tr('%(zone_name)s (m)') % {
                        'zone_name': tr(zone_name)
                    }
                row = m.Row(zone_name)

                for indicator, calculation_data in calc.iteritems():
                    value = calculation_data['value']
                    value = str(unhumanize_number(value))
                    if value == self.aggregator.get_default_keyword('NO_DATA'):
                        has_no_data = True
                        try:
                            postprocessor_totals[indicator] += 0
                        except KeyError:
                            postprocessor_totals[indicator] = 0
                    else:
                        value = int(value)
                        try:
                            postprocessor_totals[indicator] += value
                        except KeyError:
                            postprocessor_totals[indicator] = value
                    row.add(format_int(value))
                table.add(row)

            if not aoi_mode:
                # add the totals row
                row = m.Row(self.tr('Total in aggregation areas'))
                for _, total in postprocessor_totals.iteritems():
                    row.add(format_int(total))
                table.add(row)

            # add table to message
            message.add(table)
            if has_no_data:
                message.add(
                    m.EmphasizedText(
                        self.
                        tr('"%s" values mean that there where some problems while '
                           'calculating them. This did not affect the other '
                           'values.') %
                        (self.aggregator.get_default_keyword('NO_DATA'))))
            caption = m.EmphasizedText(
                self.tr(
                    'Columns and rows containing only 0 or "%s" values are '
                    'excluded from the tables.' %
                    self.aggregator.get_default_keyword('NO_DATA')))
            message.add(m.Paragraph(caption, style_class='caption'))

        return message
Exemple #29
0
def content():
    """Helper method that returns just the content.

    This method was added so that the text could be reused in the
    dock_help module.

    .. versionadded:: 3.2.2

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    message.add(
        m.Paragraph(
            tr('The InaSAFE options dialog is used to control various aspects of '
               'the InaSAFE analysis and reporting environment. Here are brief '
               'descriptions of all the options available, grouped by the tab '
               'page on which they occur.')))

    header = m.Heading(tr('Organisation Profile tab'), **INFO_STYLE)
    message.add(header)

    paragraph = m.Paragraph(m.Image(
        'file:///%s/img/screenshots/'
        'inasafe-options-organisation-screenshot.png' % resources_path()),
                            style_class='text-center')

    message.add(paragraph)
    message.add(
        m.Paragraph(
            tr('The Organisation Profile tab provides several general settings:'
               )))
    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            m.ImportantText(tr('Organisation')),
            tr(' - Use this option to specify the name of your organisation.'))
    )
    bullets.add(
        m.Text(
            m.ImportantText(tr('Contact email')),
            tr(' - Use this option to specify the contact person\'s email '
               'address to use in the generated metadata document.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Website')),
            tr(' - Use this option to set the website address to be used in '
               'the generated metadata document.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Use custom organisation logo')),
            tr(' - By default, InaSAFE will add the supporters logo to each '
               'map template. The supporters logo is also used at tbe bottom '
               'of the dock panel if the \'show organisation logo in dock\' '
               'option is enabled. You can use this option to replace the '
               'organisation logo with that of your own organisation. The logo '
               'will be rescaled automatically to fill the space provided.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Currency')),
            tr(' - InaSAFE will use the selected currency for the analysis.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Analysis license')),
            tr(' - Use this to set the usage and redistribution license for the '
               'generated impact layer.')))
    message.add(bullets)

    header = m.Heading(tr('Population Parameters tab'), **INFO_STYLE)
    message.add(header)

    paragraph = m.Paragraph(m.Image(
        'file:///%s/img/screenshots/'
        'inasafe-options-population-screenshot.png' % resources_path()),
                            style_class='text-center')
    message.add(paragraph)

    message.add(
        m.Paragraph(
            tr('In this tab you can define some parameters that will be used by '
               'InaSAFE in the analysis of exposed populations. You have the option '
               'to change the parameters for whether the exposed population is '
               'considered to be affected by each hazard type and class, and the '
               'displacement rate that will be used for affected people.')))

    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            m.ImportantText(tr('Affected')),
            tr(' - When this option is checked, people exposed to the hazard '
               'class will be included in the count of affected people.')))

    bullets.add(
        m.Text(
            m.ImportantText(tr('Displacement Rate')),
            tr(' - The displacement rate is used to estimate the number of '
               'people displaced for each hazard class. People must be affected '
               'before they can be displaced. ')))
    message.add(bullets)
    message.add(
        m.Paragraph(
            tr('Please refer to the InaSAFE manual for concept definitions and '
               'more information on the source of the hazard classifications and '
               'default settings. We really encourage you to consider these '
               'parameters carefully and to choose appropriate values for your '
               'local situation based on past events and expert knowledge.')))

    header = m.Heading(tr('GIS Environment tab'), **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(m.Image(
        'file:///%s/img/screenshots/'
        'inasafe-options-environment-screenshot.png' % resources_path()),
                            style_class='text-center')
    message.add(paragraph)

    message.add(
        m.Paragraph(
            tr('The GIS Environment tab provides several general settings:')))

    bullets = m.BulletedList()

    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Always show welcome message when opening QGIS with InaSAFE'
                   )),
            tr(' - When this option is enabled, the welcome message will be '
               'enabled when opening QGIS with InaSAFE. By default the Welcome '
               'message will be displayed.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Show organisation logo in InaSAFE dock')),
            tr(' - When this option is enabled, a logo will be displayed at the '
               'bottom of the InaSAFE dock widget. By default the logo used '
               'is the InaSAFE supporters logo, but you can alter this by '
               'setting the \'Use custom organisation logo\' option in '
               'the template options tab (see below).')))
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Show only visible layers in the InaSAFE dock')),
            tr(' - When this option is enabled layers that are not visible '
               'in the QGIS layers panel will not be shown in the hazard, '
               'exposure and aggregation combo boxes in the dock area.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Set QGIS layer name from title in keywords')),
            tr(' - If this option is enabled, the InaSAFE keywords title '
               'attribute will be used for the layer name in the QGIS Layers list '
               'when adding a layer.')))
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Zoom to impact layer on scenario estimate completion')),
            tr(' - When this option is enabled, the map view extents will '
               'be updated to match the extents of the generated impact layer '
               'once the analysis completes.')))
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Hide exposure on scenario estimate completion')),
            tr(' - Use this option if you prefer to not show the exposure '
               'layer as an underlay behind the generated impact layer.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Show only impact layer on report map')),
            tr('When this option is enabled, the map report created after an '
               'analysis completes will not show any other layers in your '
               'current project except for the impact layer. ')))
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Print atlas report on atlas driven template with the '
                   'aggregation layer')),
            tr('When this option is enabled, InaSAFE will generate an atlas '
               'report based on aggregation area if the template has atlas '
               'generation flag enabled.')))
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Use selected features only with the aggregation layer')),
            tr('If enabled, running an analysis with some features of the '
               'aggregation layer selected will constrain the analysis to only '
               'those selected aggregation areas, all others will be ignored.')
        ))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Location for results')),
            tr(' - By default, InaSAFE will write impact layer and intermediate '
               'outputs to the system temporary directory. On some operating '
               'systems, these temporary files will be deleted on each reboot. '
               'If you wish to, you can specify an alternative directory '
               'to use for storing these temporary files.')))
    message.add(bullets)

    header = m.Heading(tr('Earthquake tab'), **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(m.Image(
        'file:///%s/img/screenshots/'
        'inasafe-options-earthquake-screenshot.png' % resources_path()),
                            style_class='text-center')
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('In this tab you can select which earthquake fatality model to use '
           'when estimating earthquake impact on population. This option is '
           'global - it will affect all subsequent earthquake analyses carried '
           'out in InaSAFE.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('When selecting an earthquake analysis model, its details will be '
           'shown below in the text box area.'))
    message.add(paragraph)

    header = m.Heading(tr('Template Options tab'), **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(m.Image('file:///%s/img/screenshots/'
                                    'inasafe-options-template-screenshot.png' %
                                    resources_path()),
                            style_class='text-center')
    message.add(paragraph)

    message.add(
        m.Paragraph(
            tr('This tab has options relating to the generation of map composer '
               'templates and how reports will be printed:'
               '.')))

    bullets = m.BulletedList()

    bullets.add(
        m.Text(
            m.ImportantText(tr('Use custom north arrow image')),
            tr(' - InaSAFE provides a basic north arrow which is placed on '
               'generated map compositions and rendered PDF reports. You can '
               'replace this north arrow with one of your own choosing using '
               'this option.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Use custom disclaimer text')),
            tr(' - By default, InaSAFE will display a disclaimer on reports '
               'advising readers of the report to exercise caution when '
               'interpreting the outputs presented. You can override this '
               'text using this option, though we do advise that you include '
               'a similar statement of caution in your overridden text.')))
    message.add(bullets)

    header = m.Heading(tr('Demographic Defaults tab'), **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(m.Image(
        'file:///%s/img/screenshots/'
        'inasafe-options-demographic-screenshot.png' % resources_path()),
                            style_class='text-center')
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('In this tab you will find options for setting the default ratios '
           'for demographic groups. There is more detailed help on demographic '
           'groups within the main help page for InaSAFE in the Field Mapping '
           'Tool section. Essentially default ratios for demographic groups '
           'determine what proportion of the population are within each '
           'population group (e.g. infants versus children etc.). The options '
           'defined in this tab are used in cases where you choose to use the '
           'global default ratios while configuring the keywords for an '
           'aggregation layer as shown below.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Note that the contents of this tab may changed depending on what '
           'groups have been defined for demographic breakdowns.'))
    message.add(paragraph)
    paragraph = m.Paragraph(m.Image(
        'file:///%s/img/screenshots/'
        'field-mapping-tool-default-ratios-screenshot.png' % resources_path()),
                            style_class='text-center')
    message.add(paragraph)

    header = m.Heading(tr('Advanced tab'), **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(m.Image('file:///%s/img/screenshots/'
                                    'inasafe-options-advanced-screenshot.png' %
                                    resources_path()),
                            style_class='text-center')
    message.add(paragraph)

    message.add(
        m.Paragraph(
            tr('This tab contains options intended for advanced users only: '))
    )

    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            m.ImportantText(tr('Keyword cache for remote databases')),
            tr(' - When InaSAFE is used with remote layers (for example a '
               'database layer or a WFS layer), it is not possible to store the '
               'keywords for the layer with the layer itself. To accommodate for '
               'these types of layers, InaSAFE writes the keywords to a small '
               'file based database (using sqlite) and then retrieves them based '
               'on unique connection details used for that layer. You can '
               'specify a custom path to be used for storing the keywords '
               'database using this option.')))
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Help to improve InaSAFE by submitting errors to a '
                   'remote server')),
            tr(' - With this option enabled, InaSAFE will post any errors that '
               'occur to an online server for analysis by our development team. '
               'This option is disabled by default as some may consider some of '
               'the data submitted (IP Address, logged in user name) to be '
               'sensitive.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Enable developer mode')),
            tr(' - When this option is enabled, right clicking on the webview '
               'widget in the dock will allow you to debug the generated HTML. '
               'In addition, if the metadata.txt for the running InaSAFE is '
               'set to \'alpha\', an additional icon will be added to the '
               'toolbar to add test layers to the QGIS project.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Generate reports')),
            tr(' - When this option is enabled, InaSAFE will generate reports. '
               )))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Show memory profile')),
            tr(' - When this option is enabled, InaSAFE will display the memory '
               'profile when it runs. ')))

    message.add(bullets)

    return message
Exemple #30
0
    def run(self):
        """Run any post processors requested by the impact function.
        """
        try:
            requested_postprocessors = self.function_parameters[
                'postprocessors']
            postprocessors = get_postprocessors(
                requested_postprocessors, self.aggregator.aoi_mode)
        except (TypeError, KeyError):
            # TypeError is for when function_parameters is none
            # KeyError is for when ['postprocessors'] is unavailable
            postprocessors = {}
        LOGGER.debug('Running this postprocessors: ' + str(postprocessors))

        feature_names_attribute = self.aggregator.attributes[
            self.aggregator.get_default_keyword('AGGR_ATTR_KEY')]
        if feature_names_attribute is None:
            self.attribute_title = self.tr('Aggregation unit')
        else:
            self.attribute_title = feature_names_attribute

        name_filed_index = self.aggregator.layer.fieldNameIndex(
            self.attribute_title)
        sum_field_index = self.aggregator.layer.fieldNameIndex(
            self._sum_field_name())

        user_defined_female_ratio = False
        female_ratio_field_index = None
        female_ratio = None
        user_defined_age_ratios = False
        youth_ratio_field_index = None
        youth_ratio = None
        adult_ratio_field_index = None
        adult_ratio = None
        elderly_ratio_field_index = None
        elderly_ratio = None

        if 'Gender' in postprocessors:
            # look if we need to look for a variable female ratio in a layer
            try:
                female_ratio_field = self.aggregator.attributes[
                    self.aggregator.get_default_keyword(
                        'FEMALE_RATIO_ATTR_KEY')]
                female_ratio_field_index = \
                    self.aggregator.layer.fieldNameIndex(female_ratio_field)

                # something went wrong finding the female ratio field,
                # use defaults from below except block
                if female_ratio_field_index == -1:
                    raise KeyError

                user_defined_female_ratio = True

            except KeyError:
                try:
                    female_ratio = self.keyword_io.read_keywords(
                        self.aggregator.layer,
                        self.aggregator.get_default_keyword(
                            'FEMALE_RATIO_KEY'))
                except KeywordNotFoundError:
                    female_ratio = \
                        self.aggregator.get_default_keyword('FEMALE_RATIO')

        if 'Age' in postprocessors:
            # look if we need to look for a variable age ratio in a layer
            try:
                youth_ratio_field = self.aggregator.attributes[
                    self.aggregator.get_default_keyword(
                        'YOUTH_RATIO_ATTR_KEY')]
                youth_ratio_field_index = \
                    self.aggregator.layer.fieldNameIndex(youth_ratio_field)
                adult_ratio_field = self.aggregator.attributes[
                    self.aggregator.get_default_keyword(
                        'ADULT_RATIO_ATTR_KEY')]
                adult_ratio_field_index = \
                    self.aggregator.layer.fieldNameIndex(adult_ratio_field)
                elderly_ratio_field = self.aggregator.attributes[
                    self.aggregator.get_default_keyword(
                        'ELDERLY_RATIO_ATTR_KEY')]
                elderly_ratio_field_index = \
                    self.aggregator.layer.fieldNameIndex(elderly_ratio_field)
                # something went wrong finding the youth ratio field,
                # use defaults from below except block
                if (youth_ratio_field_index == -1 or
                        adult_ratio_field_index == -1 or
                        elderly_ratio_field_index == -1):
                    raise KeyError

                user_defined_age_ratios = True

            except KeyError:
                try:
                    youth_ratio = self.keyword_io.read_keywords(
                        self.aggregator.layer,
                        self.aggregator.get_default_keyword(
                            'YOUTH_RATIO_KEY'))
                    adult_ratio = self.keyword_io.read_keywords(
                        self.aggregator.layer,
                        self.aggregator.get_default_keyword(
                            'ADULT_RATIO_KEY'))
                    elderly_ratio = self.keyword_io.read_keywords(
                        self.aggregator.layer,
                        self.aggregator.get_default_keyword(
                            'ELDERLY_RATIO_KEY'))

                except KeywordNotFoundError:
                    youth_ratio = \
                        self.aggregator.get_default_keyword('YOUTH_RATIO')
                    adult_ratio = \
                        self.aggregator.get_default_keyword('ADULT_RATIO')
                    elderly_ratio = \
                        self.aggregator.get_default_keyword('ELDERLY_RATIO')

        if 'BuildingType' or 'RoadType' in postprocessors:
            try:
                key_attribute = self.keyword_io.read_keywords(
                    self.aggregator.exposure_layer, 'key_attribute')
            except KeywordNotFoundError:
                # use 'type' as default
                key_attribute = 'type'

        # iterate zone features
        request = QgsFeatureRequest()
        request.setFlags(QgsFeatureRequest.NoGeometry)
        provider = self.aggregator.layer.dataProvider()
        # start data retrieval: fetch no geometry and all attributes for each
        # feature
        polygon_index = 0
        for feature in provider.getFeatures(request):
            # if a feature has no field called
            if name_filed_index == -1:
                zone_name = str(feature.id())
            else:
                zone_name = feature[name_filed_index]

            # create dictionary of attributes to pass to postprocessor
            general_params = {
                'target_field': self.aggregator.target_field,
                'function_params': self.function_parameters}

            if self.aggregator.statistics_type == 'class_count':
                general_params['impact_classes'] = (
                    self.aggregator.statistics_classes)
            elif self.aggregator.statistics_type == 'sum':
                impact_total = feature[sum_field_index]
                general_params['impact_total'] = impact_total

            try:
                general_params['impact_attrs'] = (
                    self.aggregator.impact_layer_attributes[polygon_index])
            except IndexError:
                # rasters and attributeless vectors have no attributes
                general_params['impact_attrs'] = None

            for key, value in postprocessors.iteritems():
                parameters = general_params
                try:
                    # look if params are available for this postprocessor
                    parameters.update(
                        self.function_parameters[
                            'postprocessors'][key]['params'])
                except KeyError:
                    pass

                if key == 'Gender':
                    if user_defined_female_ratio:
                        female_ratio = feature[female_ratio_field_index]
                        if female_ratio is None:
                            female_ratio = self.aggregator.defaults[
                                'FEMALE_RATIO']
                            LOGGER.warning('Data Driven Female ratio '
                                           'incomplete, using defaults for'
                                           ' aggregation unit'
                                           ' %s' % feature.id)

                    parameters['female_ratio'] = female_ratio

                if key == 'Age':
                    if user_defined_age_ratios:
                        youth_ratio = feature[youth_ratio_field_index]
                        adult_ratio = feature[adult_ratio_field_index]
                        elderly_ratio = feature[elderly_ratio_field_index]
                        if (youth_ratio is None or
                                adult_ratio is None or
                                elderly_ratio is None):
                            youth_ratio = self.aggregator.defaults[
                                'YOUTH_RATIO']
                            adult_ratio = self.aggregator.defaults[
                                'ADULT_RATIO']
                            elderly_ratio = self.aggregator.defaults[
                                'ELDERLY_RATIO']
                            LOGGER.warning('Data Driven Age ratios '
                                           'incomplete, using defaults for'
                                           ' aggregation unit'
                                           ' %s' % feature.id)

                    parameters['youth_ratio'] = youth_ratio
                    parameters['adult_ratio'] = adult_ratio
                    parameters['elderly_ratio'] = elderly_ratio

                if key == 'BuildingType' or key == 'RoadType':
                    # TODO: Fix this might be referenced before assignment
                    parameters['key_attribute'] = key_attribute

                try:
                    value.setup(parameters)
                    value.process()
                    results = value.results()
                    value.clear()
                    # LOGGER.debug(results)

                    # this can raise a KeyError
                    self.output[key].append(
                        (zone_name, results))

                except PostProcessorError as e:
                    message = m.Message(
                        m.Heading(self.tr('%s postprocessor problem' % key),
                                  **styles.DETAILS_STYLE),
                        m.Paragraph(self.tr(str(e))))
                    self.error_message = message

                except KeyError:
                    self.output[key] = []
                    # TODO: Fix this might be referenced before assignment
                    self.output[key].append((zone_name, results))
            # increment the index
            polygon_index += 1