示例#1
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/'
                                    'batch-calculator-screenshot.png' %
                                    resources_path()),
                            style_class='text-center')
    message.add(paragraph)
    message.add(
        m.Paragraph(
            tr('Depending on which Impact Function you have chosen you have '
               'different options available for adjusting the parameters of the '
               'question you are asking. Some Impact Functions have more '
               'configurable Options than others. To open the Impact Function '
               'Configuration Dialog you need to click on the "Options ..." '
               'button next to the selected impact function paragraph in the '
               'InaSAFE dock. You can have up to 3 tabs visible:')))

    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            m.ImportantText(tr('Options')),
            tr('- Depending in the Impact function you selected, you can '
               'influence the result of your question here (the Impact Function) '
               'by setting different values to the defaults that will be loaded. '
               'The options available will depend on the Impact Function you '
               'choose (some Impact Functions do not allow users to change the '
               'default parameters).')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Post-processors')),
            tr('- Takes the results from the Impact Function and calculates '
               'derivative indicators, for example if you have an affected '
               'population total, the Gender postprocessor will calculate gender '
               'specific indicators such as additional nutritional requirements '
               'for pregnant women.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Minimum Needs')),
            tr('- If the analysis uses population exposure, InaSAFE calculates '
               'the minimum needs of the people affected by the impact scenario. '
               'You should refer to the minimum needs tool for configuring the '
               'global defaults used in these calculations. '),
            m.Image(
                'file:///%s/img/icons/'
                'show-minimum-needs.svg' % resources_path(),
                **SMALL_ICON_STYLE),
            tr(' This panel will let you override global defaults for a specific '
               'analysis run.')))
    message.add(bullets)
    return message
示例#2
0
def generate_expression_help(description, examples):
    """Generate the help message for QGIS Expressions.

    It will format nicely the help string with some examples.

    :param description: A description of the expression.
    :type description: basestring

    :param examples: A dictionnary of examples
    :type examples: dict

    :return: A message object.
    :rtype: message
    """
    help = m.Message()
    help.add(m.Paragraph(description))
    help.add(m.Paragraph(tr('Examples:')))
    bullets = m.BulletedList()
    for expression, result in examples.iteritems():
        if result:
            bullets.add(
                m.Text(m.ImportantText(expression), m.Text('→'),
                       m.Text(result)))
        else:
            bullets.add(m.Text(m.ImportantText(expression)))
    help.add(bullets)
    return help
示例#3
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(
        '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
示例#4
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))
示例#5
0
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
示例#6
0
    def emit_pre_run_message(self):
        """Inform the user about parameters before starting the processing."""
        title = tr('Processing started')
        details = tr(
            'Please wait - processing may take a while depending on your '
            'hardware configuration and the analysis extents and data.')
        # trap for issue 706
        try:
            exposure_name = self.exposure.name
            hazard_name = self.hazard.name
            # aggregation layer could be set to AOI so no check for that
        except AttributeError:
            title = tr('No valid layers')
            details = tr(
                'Please ensure your hazard and exposure layers are set '
                'in the question area and then press run again.')
            message = m.Message(LOGO_ELEMENT,
                                m.Heading(title, **WARNING_STYLE),
                                m.Paragraph(details))
            raise NoValidLayerError(message)
        text = m.Text(
            tr('This analysis will calculate the impact of'),
            m.EmphasizedText(hazard_name),
            tr('on'),
            m.EmphasizedText(exposure_name),
        )
        if self.aggregation is not None:
            try:
                aggregation_name = self.aggregation.name
                # noinspection PyTypeChecker
                text.add(
                    m.Text(tr('and bullet list the results'),
                           m.ImportantText(tr('aggregated by')),
                           m.EmphasizedText(aggregation_name)))
            except AttributeError:
                pass
        text.add('.')
        message = m.Message(LOGO_ELEMENT,
                            m.Heading(title, **PROGRESS_UPDATE_STYLE),
                            m.Paragraph(details), m.Paragraph(text))
        try:
            # add which postprocessors will run when appropriated
            # noinspection PyTypeChecker
            post_processors_names = self.parameters['postprocessors']
            post_processors = get_postprocessors(post_processors_names)
            message.add(
                m.Paragraph(tr('The following postprocessors will be used:')))

            bullet_list = m.BulletedList()

            for name, post_processor in post_processors.iteritems():
                bullet_list.add('%s: %s' % (get_postprocessor_human_name(name),
                                            post_processor.description()))
            message.add(bullet_list)

        except (TypeError, KeyError):
            # TypeError is for when function_parameters is none
            # KeyError is for when ['postprocessors'] is unavailable
            pass
        send_static_message(self, message)
示例#7
0
    def progress_callback(self, current_value, maximum_value, message=None):
        """GUI based callback implementation for showing progress.

        :param current_value: Current progress.
        :type current_value: int

        :param maximum_value: Maximum range (point at which task is complete.
        :type maximum_value: int

        :param message: Optional message dictionary to containing content
            we can display to the user. See safe.definitions.analysis_steps
            for an example of the expected format
        :type message: dict
        """
        report = m.Message()
        report.add(LOGO_ELEMENT)
        report.add(m.Heading(tr('Analysis status'), **INFO_STYLE))
        if message is not None:
            report.add(m.ImportantText(message['name']))
            report.add(m.Paragraph(message['description']))
        report.add(self.impact_function.performance_log_message())
        send_static_message(self, report)
        self.progress_bar.setMaximum(maximum_value)
        self.progress_bar.setValue(current_value)
        QtGui.QApplication.processEvents()
示例#8
0
    def _dict_to_row(keyword_value):
        """Helper to make a message row from a keyword where value is a dict.

        .. versionadded:: 3.2

        Use this when constructing a table from keywords to display as
        part of a message object. This variant will unpack the dict and
        present it nicely in the keyword value area as a nested table in the
        cell.

        We are expecting keyword value would be something like this:

            "{'high': ['Kawasan Rawan Bencana III'], "
            "'medium': ['Kawasan Rawan Bencana II'], "
            "'low': ['Kawasan Rawan Bencana I']}"

        Or by passing a python dict object with similar layout to above.

        i.e. A string representation of a dict where the values are lists.

        :param keyword_value: Value of the keyword to be rendered. This must
            be a string representation of a dict, or a dict.
        :type keyword_value: basestring, dict

        :returns: A table to be added into a cell in the keywords table.
        :rtype: safe.messaging.items.table
        """
        if isinstance(keyword_value, basestring):
            keyword_value = literal_eval(keyword_value)
        table = m.Table(style_class='table table-condensed')
        for key, value in keyword_value.items():
            row = m.Row()
            # First the heading
            if definition(key):
                name = definition(key)['name']
            else:
                name = tr(key.capitalize())
            row.add(m.Cell(m.ImportantText(name)))
            # Then the value. If it contains more than one element we
            # present it as a bullet list, otherwise just as simple text
            if isinstance(value, (tuple, list, dict, set)):
                if len(value) > 1:
                    bullets = m.BulletedList()
                    for item in value:
                        bullets.add(item)
                    row.add(m.Cell(bullets))
                elif len(value) == 0:
                    row.add(m.Cell(""))
                else:
                    row.add(m.Cell(value[0]))
            else:
                row.add(m.Cell(value))

            table.add(row)
        return table
示例#9
0
    def populate_bullet_list(message, information):
        """Populate a message object with bullet list.

        :param message: The message object.
        :type message: Message

        :param information: A dictionary of information.
        :type information: dict

        :return: A message object that has been updated.
        :rtype: Message
        """
        bullets = m.BulletedList()
        for key, item in information.iteritems():
            if item:
                bullets.add(
                    m.Text(m.ImportantText(key), m.Text('→'), m.Text(item)))
            else:
                bullets.add(m.Text(m.ImportantText(key)))
        message.add(bullets)
        return message
示例#10
0
 def _tabulate_zero_impact(self):
     thresholds = self.parameters['thresholds'].value
     message = m.Message()
     table = m.Table(style_class='table table-condensed table-striped')
     row = m.Row()
     label = m.ImportantText(
         tr('People in %.1f m of water') % thresholds[-1])
     content = '%s' % format_int(self.total_evacuated)
     row.add(m.Cell(label))
     row.add(m.Cell(content))
     table.add(row)
     table.caption = self.question
     message.add(table)
     message = message.to_html(suppress_newlines=True)
     return message
示例#11
0
def _citations_to_message(message, definition):
    citations = m.Message()
    bullets = m.BulletedList()
    for citation in definition['citations']:
        if citation['text'] in [None, '']:
            continue
        if citation['link'] in [None, '']:
            bullets.add(m.Paragraph(citation['text']))
        else:
            bullets.add(m.Paragraph(m.Link(citation['link'],
                                           citation['text'])))
    if not bullets.is_empty():
        citations.add(m.Paragraph(m.ImportantText(tr('Citations:'))))
        citations.add(bullets)
        message.add(citations)
示例#12
0
文件: core.py 项目: vck/inasafe
def no_population_impact_message(question):
    """Create a message that indicates that no population were impacted.

    :param question: A question sentence that will be used as the table
        caption.
    :type question: basestring

    :returns: An html document containing a nice message saying nobody was
        impacted.
    :rtype: basestring
    """
    message = m.Message()
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    label = m.ImportantText(tr('People impacted'))
    content = 0
    row.add(m.Cell(label))
    row.add(m.Cell(content))
    table.add(row)
    table.caption = question
    message.add(table)
    message = message.to_html(suppress_newlines=True)
    return message
示例#13
0
    def _value_maps_row(value_maps_keyword):
        """Helper to make a message row from a value maps.

        Expected keywords:
        'value_maps': {
            'structure': {
                'ina_structure_flood_hazard_classification': {
                    'classes': {
                        'low': [1, 2, 3],
                        'medium': [4],
                        'high': [5, 6]
                    },
                    'active': True
                },
                'ina_structure_flood_hazard_4_class_classification':
                {
                    'classes': {
                        'low': [1],
                        'medium': [2, 3, 4],
                        'high': [5, 6, 7],
                        'very_high': [8]
                    },
                    'active': False

                }
            },
            'population': {
                'ina_population_flood_hazard_classification': {
                    'classes': {
                        'low': [1],
                        'medium': [2, 3],
                        'high': [4, 5, 6]
                    },
                    'active': False
                },
                'ina_population_flood_hazard_4_class_classification':
                {
                    'classes': {
                        'low': [1, 2],
                        'medium': [3, 4],
                        'high': [4, 5, 6],
                        'very_high': [6, 7, 8]
                    },
                    'active': True
                }
            },
        }

        :param value_maps_keyword: Value of the keyword to be rendered. This
            must be a string representation of a dict, or a dict.
        :type value_maps_keyword: basestring, dict

        :returns: A table to be added into a cell in the keywords table.
        :rtype: safe.messaging.items.table
        """
        if isinstance(value_maps_keyword, basestring):
            value_maps_keyword = literal_eval(value_maps_keyword)

        table = m.Table(style_class='table table-condensed table-striped')

        i = 0
        for exposure_key, classifications in value_maps_keyword.items():
            i += 1
            exposure = definition(exposure_key)
            exposure_row = m.Row()
            exposure_row.add(m.Cell(m.ImportantText(tr('Exposure'))))
            exposure_row.add(m.Cell(exposure['name']))
            table.add(exposure_row)

            classification_row = m.Row()
            classification_row.add(
                m.Cell(m.ImportantText(tr('Classification'))))
            active_classification = None
            for classification, value in classifications.items():
                if value.get('active'):
                    active_classification = definition(classification)
                    if active_classification.get('name'):
                        classification_row.add(
                            m.Cell(active_classification['name']))
                    break

            if not active_classification:
                classification_row.add(m.Cell(tr('No classifications set.')))
                continue
            table.add(classification_row)

            header = m.Row()
            header.add(m.Cell(tr('Class name')))
            header.add(m.Cell(tr('Values')))
            table.add(header)
            classes = active_classification.get('classes')
            # Sort by value, put the lowest first
            classes = sorted(classes, key=lambda k: k['value'])
            for the_class in classes:
                value_map = classifications[
                    active_classification['key']]['classes'].get(
                        the_class['key'], [])
                row = m.Row()
                row.add(m.Cell(the_class['name']))
                row.add(m.Cell(', '.join([str(v) for v in value_map])))
                table.add(row)

            if i < len(value_maps_keyword):
                # Empty row
                empty_row = m.Row()
                empty_row.add(m.Cell(''))
                empty_row.add(m.Cell(''))
                table.add(empty_row)

        return table
示例#14
0
def extent_mode_content():
    """Helper method that returns just the content in extent mode.

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

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    header = m.Heading(tr('Use intersection of hazard and exposure layers'),
                       **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(
        tr('The largest area that can be analysed is the intersection of the '
           'hazard and exposure layers you have added. To choose this option, '
           'click \'Use intersection of hazard and exposure layers\'. '))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Sometimes it is more useful to analyse a smaller area. This could be '
           'to reduce processing time (smaller areas with process faster) or '
           'because information is only needed in a certain area (e.g. if a '
           'district only wants information for their district, not for the '
           'entire city). If you want to analyse a smaller area, there are a few '
           'different ways to do this.'))
    message.add(paragraph)
    header = m.Heading(
        tr('Use intersection of hazard, exposure and current view extent'),
        **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(
        tr('If you wish to conduct the analysis on the area currently shown in '
           'the window, you can set the analysis area to \'Use intersection of '
           'hazard, exposure and current view extent\'. If the extents of the '
           'datasets are smaller than the view extent, the analysis area will be '
           'reduced to the extents of the datasets.'))
    message.add(paragraph)
    header = m.Heading(
        tr('Use intersection of hazard, exposure and this bookmark'),
        **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(
        tr('You can also use one of your QGIS bookmarks to set the analysis '
           'area.'),
        m.ImportantText(
            tr('This option will be greyed out if you have no bookmarks.')))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('To create a bookmark, zoom to the area you want to create a bookmark '
           'for. When you are happy with the extent, click the \'New bookmark\' '
           'button in the QGIS toolbar.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('The drop down menu in the InaSAFE Analysis Area window should now be '
           'activated. When you choose a bookmark from the drop down menu it '
           'will zoom to the analysis area selected by the bookmark.'))
    message.add(paragraph)
    header = m.Heading(
        tr('Use intersection of hazard, exposure and this bounding box'),
        **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(
        tr('You can also choose the analysis area interactively by clicking '
           '\'Use intersection of hazard, exposure and this bounding box\'. This '
           'will allow you to click \'Drag on map\' which will temporarily hide '
           'this window and allow you to drag a rectangle on the map. After you '
           'have finished dragging the rectangle, this window will reappear with '
           'values in the North, South, East and West boxes. If the extents of '
           'the datasets are smaller than the user defined analysis area, the '
           'analysis area will be reduced to the extents of the datasets.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Alternatively, you can enter the coordinates directly into the '
           'N/S/E/W boxes once the \'Use intersection of hazard, exposure and '
           'this bounding box\' option is selected (using the same coordinate '
           'reference system, or CRS, as the map is currently set).'))
    message.add(paragraph)

    return message
示例#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.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
示例#16
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(
        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('Basic options tab'), **INFO_STYLE)
    message.add(header)

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

    bullets = m.BulletedList()
    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('When clipping to analysis extents, also clip features')),
            tr(' - This option only applies in cases where hazard or exposure '
               'layers are vector layers. In these cases, any feature (line or '
               'polygon) that extends beyond the analysis extents will first '
               'be clipped so that it is coincident with the analysis extent. '
               'Note that enabling this option may have some unwanted side '
               'effects. For example, if you have an area attribute, that '
               'attribute may no longer match the actual clipped polygon area. '
               )))
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Show intermediate layers generated by post processing')),
            tr(' - When enabled, the working layer used for doing by-area '
               'breakdowns of impact results will be added to the current QGIS '
               'project. You can generally leave this option disabled.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Female ratio default value')),
            tr(' - When doing an analysis that uses population as the '
               'exposure layer, various post-processors are used to produce a '
               'demographic breakdown. In the case of the gender breakdown, '
               'InaSAFE will report on how many males versus females are present '
               'in each aggregation area. If there is no female ratio attribute '
               'defined in the aggregation layer, the value in this setting will '
               'be used to determine what the ratio between males to females '
               'is.')))
    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('Template options tab'), **INFO_STYLE)
    message.add(header)

    message.add(
        m.Paragraph(
            tr('This tab has options relating to the printing of reports and the '
               'generation of map composer templates.')))

    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('Prompt me when template has missing elements')),
            tr(' - You can define your own templates in InaSAFE. In some cases '
               'critical elements on the template may be ommitted during this '
               'template definition process. Should this happen, InaSAFE can '
               'warn you when you try to use the template that it is missing '
               'vital map components.')))
    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('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('Additional template directory')),
            tr(' - When generating a print report, InaSAFE will offer a number '
               'of pre-defined templates for you to use. For example there '
               'is an A4 variant, an A3 variant and so on. You can use this '
               'option to specify additional search directories to be used '
               'when presenting a list of available templates. This is useful '
               'in cases where you have created your own custom map templates '
               'and you wish to use them for report production.')))
    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('ISO 19115 metadata tab'), **INFO_STYLE)
    message.add(header)

    message.add(
        m.Paragraph(
            tr('This tab is used to define various options related to the '
               'automated generation of ISO 19115 metadata which is associated with '
               'hazard, exposure, aggregation and impact layers.')))

    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('Analysis title')),
            tr(' - Use this to set the title value for the generated metadata '
               'document.')))
    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('Advanced tab'), **INFO_STYLE)
    message.add(header)

    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.'),
            m.Image(
                'file:///%s/img/icons/'
                'add-test-layers.svg' % resources_path(), **SMALL_ICON_STYLE)))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Use QGIS zonal statistics')),
            tr(' - Some versions of QGIS shipped with a buggy zonal statistics '
               'algorithm. With this option you can elect whether to use '
               'built in zonal statistics functions from QGIS or to use '
               'an implementation of zonal statistics included with InaSAFE. '
               'At some point in the future we expect to deprecate this feature '
               'but for now we suggest to use the InaSAFE implementation.')))
    message.add(bullets)

    return message
示例#17
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/'
                                    'analysis-area-screenshot.png' %
                                    resources_path()),
                            style_class='text-center')
    message.add(paragraph)

    paragraph = m.Paragraph(
        tr('This tool allows you to specify which geographical region should be '
           'used for your analysis. If you want to check what area will be '
           'included in your analysis, enable the \'Toggle scenario outlines\' '
           'tool on the InaSAFE toolbar:'),
        m.Image(
            'file:///%s/img/icons/'
            'toggle-rubber-bands.svg' % resources_path(), **SMALL_ICON_STYLE),
    )
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Your user defined extent will be shown on the map as a rectangle. '
           'There are a number of different modes that can be used which are '
           'described below:'))
    message.add(paragraph)
    header = m.Heading(tr('Use intersection of hazard and exposure layers'),
                       **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(
        tr('The largest area that can be analysed is the intersection of the '
           'hazard and exposure layers you have added. To choose this option, '
           'click \'Use intersection of hazard and exposure layers\'. '))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Sometimes it is more useful to analyse a smaller area. This could be '
           'to reduce processing time (smaller areas with process faster) or '
           'because information is only needed in a certain area (e.g. if a '
           'district only wants information for their district, not for the '
           'entire city). If you want to analyse a smaller area, there are a few '
           'different ways to do this.'))
    message.add(paragraph)
    header = m.Heading(
        tr('Use intersection of hazard, exposure and current view extent'),
        **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(
        tr('If you wish to conduct the analysis on the area currently shown in '
           'the window, you can set the analysis area to \'Use intersection of '
           'hazard, exposure and current view extent\'. If the extents of the '
           'datasets are smaller than the view extent, the analysis area will be '
           'reduced to the extents of the datasets.'))
    message.add(paragraph)
    header = m.Heading(
        tr('Use intersection of hazard, exposure and this bookmark'),
        **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(
        tr('You can also use one of your QGIS bookmarks to set the analysis '
           'area.'),
        m.ImportantText(
            tr('This option will be greyed out if you have no bookmarks.')))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('To create a bookmark, zoom to the area you want to create a bookmark '
           'for. When you are happy with the extent, click the \'New bookmark\' '
           'button in the QGIS toolbar.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('The drop down menu in the InaSAFE Analysis Area window should now be '
           'activated. When you choose a bookmark from the drop down menu it '
           'will zoom to the analysis area selected by the bookmark.'))
    message.add(paragraph)
    header = m.Heading(
        tr('Use intersection of hazard, exposure and this bounding box'),
        **INFO_STYLE)
    message.add(header)
    paragraph = m.Paragraph(
        tr('You can also choose the analysis area interactively by clicking '
           '\'Use intersection of hazard, exposure and this bounding box\'. This '
           'will allow you to click \'Drag on map\' which will temporarily hide '
           'this window and allow you to drag a rectangle on the map. After you '
           'have finished dragging the rectangle, this window will reappear with '
           'values in the North, South, East and West boxes. If the extents of '
           'the datasets are smaller than the user defined analysis area, the '
           'analysis area will be reduced to the extents of the datasets.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('Alternatively, you can enter the coordinates directly into the '
           'N/S/E/W boxes once the \'Use intersection of hazard, exposure and '
           'this bounding box\' option is selected (using the same coordinate '
           'reference system, or CRS, as the map is currently set).'))
    message.add(paragraph)

    return message
示例#18
0
def definition_to_message(definition,
                          message=None,
                          table_of_contents=None,
                          heading_level=None):
    """Helper function to render a definition to a message.

    :param definition: A definition dictionary (see definitions package).
    :type definition: dict

    :param message: The message that the definition should be appended to.
    :type message: safe_extras.parameters.message.Message

    :param table_of_contents: Table of contents that the headings should be
        included in.
    :type message: safe_extras.parameters.message.Message

    :param heading_level: Optional style to apply to the definition
        heading. See HEADING_LOOKUPS
    :type heading_level: int

    :returns: Message
    :rtype: str
    """

    if message is None:
        message = m.Message()

    if table_of_contents is None:
        table_of_contents = m.Message()

    if heading_level:
        _create_section_header(message,
                               table_of_contents,
                               definition['name'].replace(' ', '-'),
                               definition['name'],
                               heading_level=heading_level)
    else:
        header = m.Paragraph(m.ImportantText(definition['name']))
        message.add(header)

    # If the definition has an icon, we put the icon and description side by
    # side in a table otherwise just show the description as a paragraph
    url = _definition_icon_url(definition)
    if url is None:
        message.add(m.Paragraph(definition['description']))
        if 'citations' in definition:
            _citations_to_message(message, definition)
    else:
        LOGGER.info('Creating mini table for definition description: ' + url)
        table = m.Table(style_class='table table-condensed')
        row = m.Row()
        row.add(m.Cell(m.Image(url, **MEDIUM_ICON_STYLE)))
        row.add(m.Cell(definition['description']))
        table.add(row)
        for citation in definition['citations']:
            if citation['text'] in [None, '']:
                continue
            row = m.Row()
            row.add(m.Cell(''))
            if citation['link'] in [None, '']:
                row.add(m.Cell(citation['text']))
            else:
                row.add(m.Cell(m.Link(citation['link'], citation['text'])))
            table.add(row)
        message.add(table)

    url = _definition_screenshot_url(definition)
    if url:
        message.add(m.Paragraph(m.Image(url), style_class='text-center'))

    # types contains e.g. hazard_all
    if 'types' in definition:
        for sub_definition in definition['types']:
            definition_to_message(sub_definition,
                                  message,
                                  table_of_contents,
                                  heading_level=3)

    #
    # Notes section if available
    #

    if 'notes' in definition:
        # Start a notes details group too since we have an exposure
        message.add(m.Heading(tr('Notes:'), **DETAILS_STYLE))
        message.add(m.Heading(tr('General notes:'), **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['notes']:
            if type(note) is dict:
                bullets = _add_dict_to_bullets(bullets, note)
            elif note:
                bullets.add(m.Text(note))
        message.add(bullets)
        if 'citations' in definition:
            _citations_to_message(message, definition)

    # This only for EQ
    if 'earthquake_fatality_models' in definition:
        current_function = current_earthquake_model_name()
        paragraph = m.Paragraph(
            'The following earthquake fatality models are available in '
            'InaSAFE. Note that you need to set one of these as the '
            'active model in InaSAFE Options. The currently active model is: ',
            m.ImportantText(current_function))
        message.add(paragraph)

        models_definition = definition['earthquake_fatality_models']
        for model in models_definition:
            message.add(m.Heading(model['name'], **DETAILS_SUBGROUP_STYLE))
            if 'description' in model:
                paragraph = m.Paragraph(model['description'])
                message.add(paragraph)
            for note in model['notes']:
                paragraph = m.Paragraph(note)
                message.add(paragraph)
            _citations_to_message(message, model)

    for exposure in exposure_all:
        extra_exposure_notes = specific_notes(definition, exposure)
        if extra_exposure_notes:
            title = tr(u'Notes for exposure : {exposure_name}').format(
                exposure_name=exposure['name'])
            message.add(m.Heading(title, **DETAILS_SUBGROUP_STYLE))
            bullets = m.BulletedList()
            for note in extra_exposure_notes:
                if type(note) is dict:
                    bullets = _add_dict_to_bullets(bullets, note)
                elif note:
                    bullets.add(m.Text(note))
            message.add(bullets)

    if 'continuous_notes' in definition:
        message.add(
            m.Heading(tr('Notes for continuous datasets:'),
                      **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['continuous_notes']:
            bullets.add(m.Text(note))
        message.add(bullets)

    if 'classified_notes' in definition:
        message.add(
            m.Heading(tr('Notes for classified datasets:'),
                      **DETAILS_SUBGROUP_STYLE))
        bullets = m.BulletedList()
        for note in definition['classified_notes']:
            bullets.add(m.Text(note))
        message.add(bullets)

    if 'single_event_notes' in definition:
        message.add(m.Heading(tr('Notes for single events'), **DETAILS_STYLE))
        if len(definition['single_event_notes']) < 1:
            message.add(m.Paragraph(tr('No single event notes defined.')))
        else:
            bullets = m.BulletedList()
            for note in definition['single_event_notes']:
                bullets.add(m.Text(note))
            message.add(bullets)

    if 'multi_event_notes' in definition:
        message.add(
            m.Heading(tr('Notes for multi events / scenarios:'),
                      **DETAILS_STYLE))
        if len(definition['multi_event_notes']) < 1:
            message.add(m.Paragraph(tr('No multi-event notes defined.')))
        else:
            bullets = m.BulletedList()
            for note in definition['multi_event_notes']:
                bullets.add(m.Text(note))
            message.add(bullets)

    if 'actions' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Actions:'))))
        bullets = m.BulletedList()
        for note in definition['actions']:
            if type(note) is dict:
                bullets = _add_dict_to_bullets(bullets, note)
            elif note:
                bullets.add(m.Text(note))
        message.add(bullets)

    for exposure in exposure_all:
        extra_exposure_actions = specific_actions(definition, exposure)
        if extra_exposure_actions:
            title = tr(u'Actions for exposure : {exposure_name}').format(
                exposure_name=exposure['name'])
            message.add(m.Heading(title, **DETAILS_SUBGROUP_STYLE))
            bullets = m.BulletedList()
            for note in extra_exposure_actions:
                if type(note) is dict:
                    bullets = _add_dict_to_bullets(bullets, note)
                elif note:
                    bullets.add(m.Text(note))
            message.add(bullets)

    if 'continuous_hazard_units' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Units:'))))
        table = m.Table(style_class='table table-condensed table-striped')
        row = m.Row()
        row.add(m.Cell(tr('Name'), header=True))
        row.add(m.Cell(tr('Plural'), header=True))
        row.add(m.Cell(tr('Abbreviation'), header=True))
        row.add(m.Cell(tr('Details'), header=True))
        table.add(row)
        for unit in definition['continuous_hazard_units']:
            row = m.Row()
            row.add(m.Cell(unit['name']))
            row.add(m.Cell(unit['plural_name']))
            row.add(m.Cell(unit['abbreviation']))
            row.add(m.Cell(unit['description']))
            table.add(row)
        message.add(table)

    if 'fields' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Fields:'))))
        table = _create_fields_table()

        if 'extra_fields' in definition:
            all_fields = definition['fields'] + definition['extra_fields']
        else:
            all_fields = definition['fields']

        for field in all_fields:
            _add_field_to_table(field, table)
        message.add(table)

    if 'classifications' in definition:
        message.add(m.Heading(tr('Hazard classifications'), **DETAILS_STYLE))
        message.add(
            m.Paragraph(definitions.hazard_classification['description']))
        for inasafe_class in definition['classifications']:
            definition_to_message(inasafe_class,
                                  message,
                                  table_of_contents,
                                  heading_level=3)

    if 'classes' in definition:
        message.add(m.Paragraph(m.ImportantText(tr('Classes:'))))
        is_hazard = definition['type'] == hazard_classification_type
        if is_hazard:
            table = _make_defaults_hazard_table()
        else:
            table = _make_defaults_exposure_table()

        for inasafe_class in definition['classes']:
            row = m.Row()
            if is_hazard:
                # name() on QColor returns its hex code
                if 'color' in inasafe_class:
                    colour = inasafe_class['color'].name()
                    row.add(
                        m.Cell(u'',
                               attributes='style="background: %s;"' % colour))
                else:
                    row.add(m.Cell(u' '))

            row.add(m.Cell(inasafe_class['name']))

            if is_hazard:
                if 'affected' in inasafe_class:
                    row.add(m.Cell(tr(inasafe_class['affected'])))
                else:
                    row.add(m.Cell(tr('unspecified')))

            if is_hazard:
                if inasafe_class.get('fatality_rate') > 0:
                    # we want to show the rate as a scientific notation
                    rate = html_scientific_notation_rate(
                        inasafe_class['fatality_rate'])
                    rate = u'%s%%' % rate
                    row.add(m.Cell(rate))
                elif inasafe_class.get('fatality_rate') == 0:
                    row.add(m.Cell('0%'))
                else:
                    row.add(m.Cell(tr('unspecified')))

            if is_hazard:
                if 'displacement_rate' in inasafe_class:
                    rate = inasafe_class['displacement_rate'] * 100
                    rate = u'%.0f%%' % rate
                    row.add(m.Cell(rate))
                else:
                    row.add(m.Cell(tr('unspecified')))

            if 'string_defaults' in inasafe_class:
                defaults = None
                for default in inasafe_class['string_defaults']:
                    if defaults:
                        defaults += ',%s' % default
                    else:
                        defaults = default
                row.add(m.Cell(defaults))
            else:
                row.add(m.Cell(tr('unspecified')))

            if is_hazard:
                # Min may be a single value or a dict of values so we need
                # to check type and deal with it accordingly
                if 'numeric_default_min' in inasafe_class:
                    if isinstance(inasafe_class['numeric_default_min'], dict):
                        bullets = m.BulletedList()
                        minima = inasafe_class['numeric_default_min']
                        for key, value in minima.iteritems():
                            bullets.add(u'%s : %s' % (key, value))
                        row.add(m.Cell(bullets))
                    else:
                        row.add(m.Cell(inasafe_class['numeric_default_min']))
                else:
                    row.add(m.Cell(tr('unspecified')))

            if is_hazard:
                # Max may be a single value or a dict of values so we need
                # to check type and deal with it accordingly
                if 'numeric_default_max' in inasafe_class:
                    if isinstance(inasafe_class['numeric_default_max'], dict):
                        bullets = m.BulletedList()
                        maxima = inasafe_class['numeric_default_max']
                        for key, value in maxima.iteritems():
                            bullets.add(u'%s : %s' % (key, value))
                        row.add(m.Cell(bullets))
                    else:
                        row.add(m.Cell(inasafe_class['numeric_default_max']))
                else:
                    row.add(m.Cell(tr('unspecified')))

            table.add(row)
            # Description goes in its own row with spanning
            row = m.Row()
            row.add(m.Cell(''))
            row.add(m.Cell(inasafe_class['description'], span=7))
            table.add(row)

        # For hazard classes we also add the 'not affected' class manually:
        if definition['type'] == definitions.hazard_classification_type:
            row = m.Row()
            colour = definitions.not_exposed_class['color'].name()
            row.add(m.Cell(u'', attributes='style="background: %s;"' % colour))
            description = definitions.not_exposed_class['description']
            row.add(m.Cell(description, span=7))
            table.add(row)

        message.add(table)

    if 'affected' in definition:
        if definition['affected']:
            message.add(
                m.Paragraph(
                    tr('Exposure entities in this class ARE considered affected'
                       )))
        else:
            message.add(
                m.Paragraph(
                    tr('Exposure entities in this class are NOT considered '
                       'affected')))

    if 'optional' in definition:
        if definition['optional']:
            message.add(
                m.Paragraph(
                    tr('This class is NOT required in the hazard keywords.')))
        else:
            message.add(
                m.Paragraph(
                    tr('This class IS required in the hazard keywords.')))

    return message
示例#19
0
    def _keyword_to_row(self, keyword, value):
        """Helper to make a message row from a keyword.

        .. versionadded:: 3.2

        Use this when constructing a table from keywords to display as
        part of a message object.

        :param keyword: The keyword to be rendered.
        :type keyword: str

        :param value: Value of the keyword to be rendered.
        :type value: basestring

        :returns: A row to be added to a messaging table.
        :rtype: safe.messaging.items.row.Row
        """
        row = m.Row()
        # Translate titles explicitly if possible
        if keyword == 'title':
            value = self.tr(value)
        # we want to show the user the concept name rather than its key
        # if possible. TS
        definition = self.definition(keyword)
        if definition is None:
            definition = self.tr(keyword.capitalize().replace('_', ' '))
        else:
            definition = definition['name']

        # We deal with some special cases first:

        # In this case the value contains a DICT that we want to present nicely
        if keyword == 'value_map':
            value = self._dict_to_row(value)
        # In these KEYWORD cases we show the DESCRIPTION for
        # the VALUE definition
        elif keyword in [
                'vector_hazard_classification', 'raster_hazard_classification'
        ]:
            # get the definition for this class from definitions.py
            value = self.definition(value)
            value = value['description']
        # In these VALUE cases we show the DESCRIPTION for
        # the VALUE definition
        elif value in []:
            # get the definition for this class from definitions.py
            value = self.definition(value)
            value = value['description']
        # In these VALUE cases we show the NAME for the VALUE definition
        elif value in [
                'multiple_event', 'single_event', 'point', 'line', 'polygon'
                'field'
        ]:
            # get the name for this class from definitions.py
            value = self.definition(value)
            value = value['name']
        # otherwise just treat the keyword as literal text
        else:
            # Otherwise just directly read the value
            value = get_string(value)

        key = m.ImportantText(definition)
        row.add(m.Cell(key))
        row.add(m.Cell(value))
        return row
示例#20
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(
        tr('InaSAFE is free software that produces realistic natural hazard '
           'impact scenarios for better planning, preparedness and response '
           'activities. It provides a simple but rigourous way to combine data '
           'from scientists, local governments and communities to provide '
           'insights into the likely impacts of future disaster events.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('The InaSAFE \'dock panel\' helps you to run hazard impact analysis '
           'within the QGIS environment. It helps you create your hazard impact '
           'analysis question and shows the results of this analysis. If you are '
           'a new user, you may also consider using the \'Impact Function '
           'Centric Wizard\' to run the analysis. This wizard will guide you '
           'through the process of running an InaSAFE assessment, with '
           'interactive step by step instructions. You can launch the wizard '
           'by clicking on this icon in the toolbar:'),
        m.Image('file:///%s/img/icons/'
                'show-wizard.svg' % resources_path(), **SMALL_ICON_STYLE),
    )
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('You can drag and drop the dock panel to reposition it on the screen. '
           'For example, dragging the panel towards the right margin of the QGIS '
           'application will dock it to the right side of the screen.'))
    message.add(paragraph)

    message.add(
        m.Paragraph(tr('There are three main areas to the dock panel:')))
    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            # format 'the __questions__ area' for proper i18n
            tr('the %s area') %
            (m.ImportantText(tr('questions')).to_html(), )))
    bullets.add(
        m.Text(
            # format 'the __results__ area' for proper i18n
            tr('the %s area') % (m.ImportantText(tr('results')).to_html(), )))
    bullets.add(
        m.Text(
            # format 'the __buttons__ area' for proper i18n
            tr('the %s area') % (m.ImportantText(tr('buttons')).to_html(), )))
    message.add(bullets)
    message.add(
        m.Paragraph(
            tr('You can get help at any time in InaSAFE by clicking on the '
               'help buttons provided on each dock and dialog.')))

    header = m.Heading(tr('The questions area'), **INFO_STYLE)
    message.add(header)
    message.add(
        m.Paragraph(
            tr('The intention of InaSAFE is to make it easy to perform your impact '
               'analysis. We start the analysis in the questions area. This area '
               'contains three drop down menus. You create your question by using '
               'these drop down menus to select the hazard and exposure data you '
               'wish to perform the analysis on. '
               'All questions follow this form:'),
            m.EmphasizedText(
                tr('In the event of a [hazard], how many [exposure] might be '
                   '[impacted]?'))))
    message.add(
        m.Paragraph(
            tr('For example: "If there is a flood, how many buildings might be '
               'flooded?"')))
    message.add(
        m.Paragraph(
            tr('InaSAFE can be used to answer such questions for hazards such as '
               'flood, tsunami, volcanic ash fall and earthquake and exposures '
               'such as population, roads, structures, land cover etc.')))
    message.add(
        m.Paragraph(
            tr('The first step in answering these questions is to load layers that '
               'represent either hazard scenarios or exposure data into QGIS. '
               'A hazard, for example, may be represented as a raster layer in '
               'QGIS where each pixel in the raster represents the flood depth '
               'following an inundation event. An exposure layer could be '
               'represented, for example, as vector polygon data representing '
               'building outlines, or a raster outline where each pixel represents '
               'the number of people thought to be living in that cell.')))
    message.add(
        m.Paragraph(
            tr('InaSAFE will combine these two layers in a '
               'mathematical model. The results of this model will show what the '
               'effect of the hazard will be on the exposed infrastructure or '
               'people. The plugin relies on simple keyword metadata '
               'associated with each layer to determine what kind of information the '
               'layer represents. You can define these keywords by '
               'selecting a layer and then clicking the InaSAFE Keywords Wizard icon '
               'on the toolbar: '),
            m.Image(
                'file:///%s/img/icons/'
                'show-keyword-wizard.svg' % resources_path(),
                **SMALL_ICON_STYLE),
            tr('The wizard will guide you through the process of defining the '
               'keywords for that layer.')))
    message.add(
        m.Paragraph(
            tr('Aggregation is the process whereby we group the analysis results '
               'by district so that you can see how many people, roads or '
               'buildings were affected in each area. This will help you to '
               'understand where the most critical needs are.  Aggregation is '
               'optional in InaSAFE - if you do not use aggregation, the entire '
               'analysis area will be used for the data summaries. Typically '
               'aggregation layers in InaSAFE have the name of the district or '
               'reporting area as attributes. It is also possible to use extended '
               'attributes to indicate the ratio of men and women; youth, adults '
               'and elderly living in each area. Where these are provided and the '
               'exposure layer is population, InaSAFE will provide a demographic '
               'breakdown per aggregation area indicating how many men, women, etc. '
               'were probably affected in that area.')))

    header = m.Heading(tr('The results area'), **INFO_STYLE)
    message.add(header)

    message.add(
        m.Paragraph(
            tr('After running an analysis, the question area is hidden to maximise '
               'the amount of space allocated to the results area. You can '
               're-open the question area at any time by pressing the \'show '
               'question form\' button.')))

    message.add(
        m.Paragraph(
            tr('The results area is used to display various useful feedback items to '
               'the user. Once an impact scenario has been run, a summary table will '
               'be shown.')))

    message.add(
        m.Paragraph(
            tr('If you select an impact layer (i.e. a layer that was produced using '
               'an InaSAFE Impact Function), in the QGIS layers list, this summary '
               'will also be displayed in the results area. When you select a hazard '
               'or exposure layer in the QGIS layers list, the keywords for that '
               'layer will be shown in the results area, making it easy to '
               'understand what metadata exists for that layer.')))

    message.add(
        m.Paragraph(
            tr('The results area is also used to display status information. For '
               'example, during the analysis process, the status area will display '
               'notes about each step in the analysis process. The \'Run\' '
               'button will be activated when both a valid hazard and valid exposure '
               'layer have been added in QGIS.')))

    message.add(
        m.Paragraph(
            tr('Finally, the results area is also used to display any error messages '
               'so that you can see what went wrong and why. You may need to '
               'scroll down to view the message completely to see all of the error '
               'message details.')))

    message.add(
        m.Paragraph(
            tr('After running the impact scenario calculation, the question is '
               'automatically hidden to make the results area as large as possible. '
               'If you want to see what the question used in the analysis was, click '
               'on the \'Show question form\' button at the top of the results area.'
               )))

    message.add(
        m.Paragraph(
            tr('If you want to hide the question area again to have more space to '
               'display the results, click on the layer you just calculated '
               'with InaSAFE in the Layers list of QGIS to make it active.')))

    header = m.Heading(tr('The buttons area'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr('The buttons area contains four buttons:')))
    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            m.ImportantText(tr('Help')),
            tr('- click on this if you need context help, such as the document '
               'you are reading right now!')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('About')),
            tr('- click on this to see short credits for the InaSAFE project.')
        ))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Print')),
            tr('... - click on this if you wish to create a pdf of your '
               'impact scenario project or generate a report to open in '
               'composer for further tuning. An impact layer must be active '
               'before the \'Print\' button will be enabled.')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('Run')),
            tr('- this button is enabled when the combination of hazard and '
               'exposure selected in the questions area\'s drop down menus will '
               'allow you to run a scenario.')))
    message.add(bullets)

    header = m.Heading(tr('Data conversions'), **INFO_STYLE)
    message.add(header)

    message.add(
        m.Paragraph(
            tr('When running a scenario, the data being used needs to be processed '
               'into a state where it is acceptable for use by InaSAFE. '
               'In particular it should be noted that:')))

    bullets = m.BulletedList()
    bullets.add(
        tr('Remote datasets will be copied locally before processing.'))
    bullets.add(
        m.Text(
            tr('All datasets will be clipped to the behaviours defined in the '
               'analysis extents dialog if you do not use an aggregation layer.'
               ),
            m.Image(
                'file:///%s/img/icons/'
                'set-extents-tool.svg' % resources_path(),
                **SMALL_ICON_STYLE)))
    bullets.add(
        m.Text(
            tr('You can visualise the area that will be used for the analysis '
               'by enabling the "Toggle Scenario Outlines" tool. When this tool '
               'is enabled, a line (green by default) will be drawn around the '
               'outermost boundary of the analysis area.'),
            m.Image(
                'file:///%s/img/icons/'
                'toggle-rubber-bands.svg' % resources_path(),
                **SMALL_ICON_STYLE)))
    bullets.add(
        m.Text(
            tr('When you have selected an aggregation layer the analysis area '
               'will be the outline of the aggregation layer. If you select one '
               'or more polygons in the aggregation layer (by using the QGIS '
               'feature selection tools), the analysis boundary will be reduced '
               'to just the outline of these selected polygons. If the "Toggle '
               'Scenario Outlines" tool is enabled, the preview of the effective '
               'analysis area will be updated to reflect the selected features.'
               ), ))
    bullets.add(
        tr('All clipped datasets will be converted (reprojected) to the '
           'Coordinate Reference System of the exposure layer '
           'before analysis.'))
    message.add(bullets)

    header = m.Heading(tr('Generating impact reports'), **INFO_STYLE)
    message.add(header)

    message.add(
        m.Paragraph(
            tr('When the impact analysis has completed you may want to generate a '
               'report. Usually the \'Print...\'  button will be enabled immediately '
               'after analysis. Selecting an InaSAFE impact layer in QGIS Layers '
               'panel will also enable it.')))

    # This adds the help content of the print dialog
    message.add(report())
    return message
示例#21
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('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('InaSAFE reports')),
            tr(' - There are four checkboxes available which are representing '
               'the type of report component that will be generated.')))
    text = 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) and from qgis '
        'setting directory ({qgis_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.')
    qgis_directory = join(QgsApplication.qgisSettingsDirPath(), 'inasafe')
    bullets.add(
        m.Text(m.ImportantText(tr('Map reports')),
               text.format(qgis_directory=qgis_directory)))
    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)

    message.add(
        m.Paragraph(
            tr('There are four options on which template would you use to generate '
               'a map report.')))

    bullets = m.BulletedList()
    bullets.add(
        m.Text(
            m.ImportantText(tr('InaSAFE default templates')),
            tr(' - The map report will be generated using InaSAFE default '
               'landscape and portrait map templates. Override template will '
               'not be used.')))

    bullets.add(
        m.Text(
            m.ImportantText(tr('Override template')),
            tr(' - The map report will be generated using override template '
               'found from qgis setting directory. InaSAFE default map templates '
               'will not be printed.')))

    bullets.add(
        m.Text(
            m.ImportantText(tr('Template from search directory')),
            tr(' - The map report will be generated using selected template on '
               'template dropdown selector. InaSAFE default map templates will '
               'not be printed and override template will not be used.')))

    bullets.add(
        m.Text(
            m.ImportantText(tr('Template from file system')),
            tr(' - The map report will be generated using selected template on '
               'file system. InaSAFE default map templates will not be printed '
               'and override template will not be used.')))

    message.add(bullets)

    return message
示例#22
0
def field_mapping_help_content():
    """Helper method that returns just the content in extent mode.

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

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    message = m.Message()
    paragraph = m.Paragraph(
        tr('Field mapping describes the process of matching one or more fields '
           'in an attribute table to a concept in InaSAFE. The field mappings '
           'tool InaSAFE allows you to match concepts such as "elderly", '
           '"disabled people", "pregnant" and so on to their counterpart fields '
           'in either an aggregation layer or an exposure population vector '
           'layer.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        m.ImportantText(
            'Note: It is not possible to use this tool with raster population '
            'exposure data, but ratios defined in aggregation layers will be '
            'used when raster exposure population data is used.'))
    message.add(paragraph)

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

    paragraph = m.Paragraph(
        tr('The illustration above shows the principle behind InaSAFE\'s '
           'demographic breakdown reporting system. The idea here is to support '
           'the production of a detailed demographic breakdown when carrying out '
           'an analysis with a population exposure vector dataset. So for '
           'example instead of simply reporting on the total number of people '
           'exposed to a hazard, we want to break down the affected population '
           'into distinct demographic groups. In InaSAFE by default we consider '
           'three groups:'))
    message.add(paragraph)

    bullets = m.BulletedList()
    bullets.add(
        m.Paragraph(
            m.ImportantText(tr('Gender: ')),
            tr('The gender group reports on gender specific demographics '
               'including things like the number of women of child bearing age, '
               'number of pregnant women, number of lactating women and so on.'
               )))
    bullets.add(
        m.Paragraph(
            m.ImportantText(tr('Age: ')),
            tr('The age group reports on age specific demographics including '
               'things like the number of infants, children, young adults, '
               'adults elderly people and so on.')))
    bullets.add(
        m.Paragraph(
            m.ImportantText(tr('Vulnerable people: ')),
            tr('The vulnerable people group reports on specific demographics '
               'relating to vulnerability including things like the number of '
               'infants, elderly people, disabled people and so on.')))
    message.add(bullets)
    paragraph = m.Paragraph(
        tr('In the diagram above, you can see that we have an "age" group '
           '(column on the right) which, for purposes of illustration, has two '
           'age classes: "infant" and "child" (center column). These age classes '
           'are defined in InaSAFE metadata and there are actually five classes '
           'in a default installation. In the left hand column you can see a '
           'number of columns listed from the attribute table. In this example '
           'our population data contains columns for different age ranges ('
           '0-1, 1-2, 2-4, 4-6). The field mapping tool can be used in order '
           'to combine the data in the "0 - 1" and "1 - 2" columns into a '
           'new column called "infant". In the next section of this document we '
           'enumerate the different groups and concepts that InaSAFE supports '
           'when generating demographic breakdowns.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('When the tool is used, it will write additional data to the '
           'exposure or aggregation layer keywords so that your preferred '
           'concept mappings will be used when reports are generated after the '
           'analysis is carried out. You should note the following special '
           'characteristics of the field mapping tool when used for aggregation '
           'datasets versus when used for vector population exposure datasets:'
           ))
    message.add(paragraph)
    paragraph = m.Paragraph(
        m.ImportantText(tr('Aggregation datasets: ')),
        tr('For aggregation datasets, the field mapping tool uses global '
           'defaults (see the InaSAFE Options Dialog documentation for more '
           'details) or dataset level defaults to determine which ratios '
           'should be used to calculate concept values. For example, in the '
           'age group the aggregation dataset may specify that infants '
           'should by calculated as a ratio of 0.1% of the total population. '
           'Note that for aggregation datasets you can only use ratios, '
           'not counts.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        m.ImportantText(tr('Vector population exposure datasets: ')),
        tr('For exposure datasets, ratios are not supported, only counts. '
           'The field mappings carried out here will be used to generate '
           'new columns during a pre-processing step before the actual '
           'analysis is carried out.'))
    message.add(paragraph)
    paragraph = m.Paragraph(
        tr('The interplay between default ratios, aggregation layer '
           'provided ratios and population exposure layers is illustrated '
           'in the table below.'))
    message.add(paragraph)

    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Aggregation'), header=True))
    row.add(m.Cell(tr('Raster'), header=True))
    row.add(m.Cell(tr('Vector, no counts'), header=True))
    row.add(m.Cell(tr('Vector with counts'), header=True))
    row.add(m.Cell(tr('Notes'), header=True))
    table.add(row)
    row = m.Row([
        tr('No aggregation'),
        tr('Use global default ratio'),
        tr('Use global default ratio'),
        tr('Use count to determine ratio'),
        tr(''),
    ])
    table.add(row)
    row = m.Row([
        tr('Aggregation, ratio not set'),
        tr('Use global default ratio'),
        tr('Do nothing'),
        tr('Use count to determine ratio'),
        tr(''),
    ])
    table.add(row)
    row = m.Row([
        tr('Aggregation, ratio value set'),
        tr('Use aggregation layer ratio'),
        tr('Use aggregation layer ratio'),
        tr('Use count to determine ratio'),
        tr(''),
    ])
    table.add(row)
    row = m.Row([
        tr('Aggregation, ratio field mapping set'),
        tr('Use aggregation layer ratio'),
        tr('Use aggregation layer ratio'),
        tr('Use count to determine ratio'),
        tr(''),
    ])
    table.add(row)
    message.add(table)

    return message
示例#23
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(tr(
        'This document describes the usage of the InaSAFE \'dock panel\''
        '- which is an interface for running risk scenarios within the QGIS '
        'environment. If you are a new user, you may also consider using the '
        '\'Impact Function Centric Wizard\' to run the analysis. You can '
        'launch the wizard by clicking on this icon in the toolbar:'),
        m.Image(
            'file:///%s/img/icons/'
            'show-wizard.svg' % resources_path(),
            **SMALL_ICON_STYLE),

    )
    message.add(paragraph)
    paragraph = m.Paragraph(tr(
        'You can drag and drop the dock panel to reposition it in the user '
        'interface. For example, dragging the panel towards the right margin '
        'of the QGIS application will dock it to the right side of the screen.'
    ))
    message.add(paragraph)

    message.add(m.Paragraph(tr(
        'There are three main areas to the dock panel:')))
    bullets = m.BulletedList()
    bullets.add(tr('the Questions area'))
    bullets.add(tr('the Results area'))
    bullets.add(tr('the Buttons area'))
    message.add(bullets)
    message.add(m.Paragraph(tr(
        'At any time you can obtain help in InaSAFE by clicking on the '
        'help buttons provided on each dock and dialog.')))

    header = m.Heading(tr('The questions area'), **INFO_STYLE)
    message.add(header)
    message.add(m.Paragraph(tr(
        'The intention of InaSAFE is to make it really simple and easy to '
        'perform your impact analysis. The question area provides a simple '
        'way for you to formulate what it is you want to find out? All '
        'questions are formulated in the form:'),
        m.EmphasizedText(tr(
            'In the event of a [hazard], how many [exposure] might be '
            'affected?'))))
    message.add(m.Paragraph(tr(
        'For example: "If there is a flood, how many buildings might be '
        'affected?"')))
    message.add(m.Paragraph(tr(
        'In order to answer such questions, the InaSAFE developers have '
        'built a number of Impact Functions that cover scenarios such as '
        'flood, tsunami, volcanic fall, earthquake and so on.')))
    message.add(m.Paragraph(tr(
        'The formulation of these questions if carried out by loading layers '
        'into QGIS that represent either hazard scenarios or exposure data.'
        'A hazard, for example, may be represented as, a raster layer in '
        'QGIS where each pixel in the raster represents the current flood '
        'depth following an inundation event. An exposure layer could be '
        'represented, for example, as vector polygon data representing '
        'building outlines, or a raster outline where each pixel represents '
        'the number of people thought to be resident in that cell.')))
    message.add(m.Paragraph(tr(
        'The impact function will combine these two input layers in a '
        'mathematical model in order to derive what the impacts of the '
        'hazard will be on the exposure infrastructure or people. By '
        'selecting a combination from the hazard and exposure combo boxes, '
        'an appropriate set of impact functions will be listed in the '
        'combo box. You may be wondering how the InaSAFE plugin determines '
        'whether a layer should be listed in the hazard or exposure combo '
        'boxes? The plugin relies on simple keyword metadata to be associated '
        'with each layer. You can define these keywords by selecting a layer '
        'and then clicking the InaSAFE Keywords Wizard icon on the toolbar: '),
        m.Image(
            'file:///%s/img/icons/'
            'show-keyword-wizard.svg' % resources_path(),
            **SMALL_ICON_STYLE),
        tr(
            'The wizard will guide you through the process of defining the '
            'keywords for that layer.')))
    message.add(m.Paragraph(tr(
        'Based on the combination of hazard and exposure layers that are '
        'selected, the Impact Function list (shown in the combo box under '
        '"Might" in the InaSAFE dock panel)  will be updated. Each impact '
        'function can only work with specific combinations of hazard and '
        'exposure types, so the options shown here will be limited '
        'accordingly. The chosen impact function can be configured (if '
        'applicable) by pressing the small ellipses (...) button next to '
        'the chosen impact function. This is explained in more detail below '
        'under the heading "Setting Analysis Parameters".')))
    message.add(m.Paragraph(tr(
        'Aggregation is the process whereby we group the results of the '
        'analysis by district so that you can see how many people, roads or '
        'buildings were affected in each area. This will help you to '
        'understand where the most critical needs are. Aggregation is '
        'optional in InaSAFE - if you do not use aggregation, the entire '
        'analysis area will be used for the data summaries. Typically '
        'aggregation layers in InaSAFE have as attributes the name of the '
        'district or reporting area. It is also possible to use extended '
        'attributes to indicate the ratio of men and women; youth, adults '
        'and elderly living in each area. Where these are provided and the '
        'exposure layer is population, InaSAFE will provide a demographic '
        'breakdown per aggregation area indicating how many men, women etc. '
        'were probably affected in that area.'
    )))

    header = m.Heading(tr('The results area'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'After running an analysis, the question area is hidden to maximise '
        'the amount of space allocated to the results area. You can '
        're-open the question area at any time by pressing the "show question '
        'form" button.')))

    message.add(m.Paragraph(tr(
        'The Results area is used to display various useful feedback items to '
        'the user. Once an impact scenario has been run, a summary table will '
        'be shown.')))

    message.add(m.Paragraph(tr(
        'If you select an impact layer (i.e. a layer that was produced using '
        'an InaSAFE impact function), in the QGIS layers list, this summary '
        'will also be displayed in the results area. When you select a hazard '
        'or exposure layer in the QGIS layers list, the keywords for that '
        'layer will be shown in the Results area, making it easy to '
        'understand what metadata exists for that layer.')))

    message.add(m.Paragraph(tr(
        'The Results area is also used to display status information. For '
        'example, when a suitable combination of hazard, exposure and impact '
        'function are selected, the results area will be updated to indicate '
        'that you can proceed to run the impact scenario calculation. The Run '
        'Button will be activated.'
    )))

    message.add(m.Paragraph(tr(
        'Finally, the Results area is also used to display any error messages '
        'so that the user is informed as to what went wrong and why. You '
        'might want to scroll down a bit in the messaging window to view the '
        'message completely.'
    )))

    message.add(m.Paragraph(tr(
        'To have more space for the results available your Question is '
        'automatically hidden to make the results area as large as possible '
        'to display the results. If you want to have a look again what the '
        'question was that you formulated click on the Show question form '
        'button on top of the result area.'
    )))

    message.add(m.Paragraph(tr(
        'If you want to hide the question area again to have more space to '
        'display the results again, just make the Layer you just calculated '
        'with InaSAFE active again in the Layers list of QGIS.'
    )))

    header = m.Heading(tr('The Buttons Area'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'The buttons area contains four buttons:')))
    bullets = m.BulletedList()
    bullets.add(m.Text(
        m.ImportantText(tr('Help')),
        tr(
            '- click on this if you need context help, such as the document '
            'you are reading right now!')))
    bullets.add(m.Text(
        m.ImportantText(tr('About')),
        tr(
            '- click on this to see short credits for the InaSAFE project.')))
    bullets.add(m.Text(
        m.ImportantText(tr('Help')),
        tr(
            'Print... - click on this if you wish to create a pdf of your '
            'impact scenarion project or just generate report and open it in '
            'composer for further tuning. An impact layer must be active '
            'before the Print button will be enabled.')))
    bullets.add(m.Text(
        m.ImportantText(tr('Run')),
        tr(
            '- Run - if the combination of options in the Questions area\'s '
            'combo boxes will allow you to run a scenario, this button is '
            'enabled.')))
    message.add(bullets)

    header = m.Heading(tr('Data conversions'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'When running a scenario, the data being used needs to be processed '
        'into a state where it is acceptable for use by the impact function. '
        'In particular it should be noted that:')))

    bullets = m.BulletedList()
    bullets.add(tr(
        'Remote datasets will be copied locally before processing.'))
    bullets.add(m.Text(
        tr(
            'All datasets will be clipped to the intersection of the hazard '
            'layer, exposure layer and the current view extents unless '
            'you have specified a different clipping behaviour in the '
            'extents selector dialog.'),
        m.Image(
            'file:///%s/img/icons/'
            'set-extents-tool.svg' % resources_path(),
            **SMALL_ICON_STYLE)
    ))
    bullets.add(tr(
        'All clipped datasets will be converted (reprojected) to Geographic '
        '(EPSG:4326) coordinate reference system before analysis.'))
    message.add(bullets)

    header = m.Heading(tr('Analysis parameters'), **INFO_STYLE)
    message.add(header)
    # this adds the help content from the IF options dialog
    message.add(options())

    header = m.Heading(tr('Generating impact reports'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'When the scenario analysis completed you may want to generate a '
        'report. Usually the "Print..."  button will be enabled immediately '
        'after analysis. Selecting an InaSAFE impact layer in QGIS Layers '
        'panel will also enable it.'
    )))

    # This adds the help content of the print dialog
    message.add(report())
    return message
示例#24
0
    def _dict_to_row(keyword_value, keyword_property=None):
        """Helper to make a message row from a keyword where value is a dict.

        .. versionadded:: 3.2

        Use this when constructing a table from keywords to display as
        part of a message object. This variant will unpack the dict and
        present it nicely in the keyword value area as a nested table in the
        cell.

        We are expecting keyword value would be something like this:

            "{'high': ['Kawasan Rawan Bencana III'], "
            "'medium': ['Kawasan Rawan Bencana II'], "
            "'low': ['Kawasan Rawan Bencana I']}"

        Or by passing a python dict object with similar layout to above.

        i.e. A string representation of a dict where the values are lists.

        :param keyword_value: Value of the keyword to be rendered. This must
            be a string representation of a dict, or a dict.
        :type keyword_value: basestring, dict

        :param keyword_property: The definition of the keyword property.
        :type keyword_property: dict, None

        :returns: A table to be added into a cell in the keywords table.
        :rtype: safe.messaging.items.table
        """
        if isinstance(keyword_value, str):
            keyword_value = literal_eval(keyword_value)
        table = m.Table(style_class='table table-condensed')
        # Sorting the key
        for key in sorted(keyword_value.keys()):
            value = keyword_value[key]
            row = m.Row()
            # First the heading
            if keyword_property is None:
                if definition(key):
                    name = definition(key)['name']
                else:
                    name = tr(key.replace('_', ' ').capitalize())
            else:
                default_name = tr(key.replace('_', ' ').capitalize())
                name = keyword_property.get('member_names',
                                            {}).get(key, default_name)

            row.add(m.Cell(m.ImportantText(name)))
            # Then the value. If it contains more than one element we
            # present it as a bullet list, otherwise just as simple text
            if isinstance(value, (tuple, list, dict, set)):
                if len(value) > 1:
                    bullets = m.BulletedList()
                    for item in value:
                        bullets.add(item)
                    row.add(m.Cell(bullets))
                elif len(value) == 0:
                    row.add(m.Cell(""))
                else:
                    row.add(m.Cell(value[0]))
            else:
                if keyword_property == property_extra_keywords:
                    key_definition = definition(key)
                    if key_definition and key_definition.get('options'):
                        value_definition = definition(value)
                        if value_definition:
                            value = value_definition.get('name', value)
                    elif key_definition and key_definition.get(
                            'type') == datetime:
                        try:
                            value = datetime.strptime(
                                value, key_definition['store_format'])
                            value = value.strftime(
                                key_definition['show_format'])
                        except ValueError:
                            try:
                                value = datetime.strptime(
                                    value, key_definition['store_format2'])
                                value = value.strftime(
                                    key_definition['show_format'])
                            except ValueError:
                                pass
                row.add(m.Cell(value))

            table.add(row)
        return table
示例#25
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(
        'In some cases you may wish to create a report containing the '
        'combined output of two impact functions for the same area for the '
        'same hazard, different exposures. For example You may carry out an '
        'assessment of the impact of a flood on population and on buildings '
        'and combine the results into a single report. The impact layer '
        'merge tool allows you to do this.'
    )))

    header = m.Heading(tr('Prerequisites'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'In order to use this tool, please bear in mind the following '
        'requirements:'
    )))
    bullets = m.BulletedList()
    bullets.add(tr(
        'Both impact layers should be loaded in your current project.'))
    bullets.add(tr(
        'Both impact layers should have been created for the same '
        'geographic region.'))
    bullets.add(tr(
        'The same aggregation area should be used for both assessments.'
    ))
    message.add(bullets)

    header = m.Heading(tr('Procedure'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'To use this tool, follow this procedure:'
    )))

    bullets = m.BulletedList()
    bullets.add(tr(
        'Run an impact assessment for an area using aggregation. e.g. '
        'Flood Impact on Buildings aggregated by municipal boundaries.'
    ))
    bullets.add(tr(
        'Run a second impact assessment for the same area using the same '
        'aggregation. e.g. Flood Impact on People aggregated by municipal '
        'boundaries.'))
    bullets.add(tr(
        'Open impact merge tool and select each impact layer from the pick '
        'lists provided.'
    ))
    bullets.add(tr(
        'Select the aggregation layer that was used to generate the first '
        'and second impact layer.'
    ))
    bullets.add(tr(
        'Select an output directory.'
    ))
    bullets.add(tr(
        'Check "Use customized report template" checkbox and select the '
        'report template file if you want to use your own template. Note '
        'that all the map composer components that are needed must be '
        'fulfilled.'
    ))
    bullets.add(tr(
        'Click OK to generate the per aggregation area combined summaries.'
    ))
    message.add(bullets)

    header = m.Heading(tr('Generated outputs'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'The tool will generate a PDF per aggregation area. The PDFs will be '
        'placed in the designated output directory after completion of the '
        'merge process.'
    )))

    message.add(m.Paragraph(tr(
        'In the case of impact assessments where no aggregation has been '
        'used, only a single pdf report is generated. In the case of impact '
        'assessments where aggregation has been used, one pdf is generated '
        'per aggregation area.')))

    message.add(m.Paragraph(
        m.ImportantText(tr('Note:')),
        m.Text(tr(
            'After report generation completes, the output directory will '
            'be opened automatically.'))
    ))

    header = m.Heading(tr('Using Customized Template'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'The default template report is located in '
        '/resources/qgis-composer-templates/merged-report.qpt. If that '
        'template does not satisfy your needs, you can use your own report '
        'template. Before using your own report template, make sure that '
        'your template contains all of these elements with id:'
    )))

    bullets = m.BulletedList()
    bullets.add(m.Text(
        m.ImportantText(tr('impact-map')),
        tr('- a QgsComposerMap')))
    bullets.add(m.Text(
        m.ImportantText(tr('safe-logo')),
        tr('- a QgsComposerPicture')))
    bullets.add(m.Text(
        m.ImportantText(tr('summary-report')),
        tr('- a QgsComposerLabel')))
    bullets.add(m.Text(
        m.ImportantText(tr('aggregation-area')),
        tr('- a QgsComposerLabel')))
    bullets.add(m.Text(
        m.ImportantText(tr('map-scale')),
        tr('- a QgsComposerScaleBar')))
    bullets.add(m.Text(
        m.ImportantText(tr('map-legend')),
        tr('- a QgsComposerLegend')))
    bullets.add(m.Text(
        m.ImportantText(tr('organisation-logo')),
        tr('- a QgsComposerPicture')))
    bullets.add(m.Text(
        m.ImportantText(tr('merged-report-table')),
        tr('- a QgsComposerHTML')))
    message.add(bullets)

    message.add(m.Paragraph(
        m.ImportantText(tr('Note:')),
        m.Text(tr(
            'You can arrange those elements in any position you want.'))
    ))

    message.add(m.Paragraph(tr(
        'If any of those elements does not exist on the report template, the '
        'tools will give you the information of what element is missing on '
        'the template.'
    )))

    header = m.Heading(tr('Map Template Elements'), **INFO_STYLE)
    message.add(header)

    message.add(m.Paragraph(tr(
        'In terms of value replacement, there are three groups of elements '
        'on the template:')))

    message.add(m.Paragraph(
        m.ImportantText(tr('Options driven elements')),
        tr(
            '- Elements that can be changed on InaSAFE Options tool. To '
            'change the value of these elements, please go to InaSAFE '
            'Option tools and change the value of the related field. '
            'Those elements are:')))

    bullets = m.BulletedList()
    bullets.add(m.Text(
        m.ImportantText(tr('organisation-logo')),
        tr(
            'This corresponds to the Organisation logo field in InaSAFE '
            'Option tools. If you do not fill this field, then the default '
            'one, supporters logo, will be used.')))
    bullets.add(m.Text(
        m.ImportantText(tr('disclaimer')),
        tr(
            'It corresponds to Disclaimer text field on InaSAFE Option '
            'tools. If you do not fill this field, then the default one will '
            'be used.')))

    message.add(m.Paragraph(
        m.ImportantText(tr('Elements containing tokens')),
        tr(
            '- the id of these element is not significant, only the token it '
            'contains. At render time, any of these tokens will be replaced. '
            'If you want to have a label containing value of these elements, '
            'enclose these elements with [] on a label i.e [impact-title] '
            'or [hazard-title]. Those elements are listed below:')))

    bullets = m.BulletedList()
    bullets.add(m.Text(
        m.ImportantText(tr('impact-title')),
        tr(
            'It indicates the title of two impacts. The value will be '
            '"first_impact_title and second_impact_title"')))
    bullets.add(m.Text(
        m.ImportantText(tr('hazard-title')),
        tr(
            'It indicates the hazard title used to generate the '
            'impact layer.')))

    message.add(m.Paragraph(
        m.ImportantText(tr(
            'Elements that are directly updated by the renderer')),
        tr(
            '- all of these elements below are generated automatically by '
            'the tool.')))

    bullets = m.BulletedList()
    bullets.add(m.Text(
        m.ImportantText(tr('impact-map')),
        tr(
            ' - contains the map of two impact layers.')))
    bullets.add(m.Text(
        m.ImportantText(tr('summary-report')),
        tr(
            ' - contains the summary of the impact from two impact layers.')))
    bullets.add(m.Text(
        m.ImportantText(tr('aggregation-area')),
        tr(
            ' - contains the name of the aggregation area.')))
    bullets.add(m.Text(
        m.ImportantText(tr('map-scale')),
        tr(
            ' - indicates the scale of the map. To work with any layer '
            'projection preferences, we encourage you to use a numeric '
            'scale bar.')))
    bullets.add(m.Text(
        m.ImportantText(tr('map-legend')),
        tr(
            ' - shows the legend of merged impact layers. The map legend '
            'on default template is set to have two columns showing each '
            'impact layer legend.')))
    bullets.add(m.Text(
        m.ImportantText(tr('merged-report-table')),
        tr(
            '- contains the detailed information of each impact.')))
    message.add(bullets)

    return message
示例#26
0
    def _keyword_to_row(self, keyword, value, wrap_slash=False):
        """Helper to make a message row from a keyword.

        .. versionadded:: 3.2

        Use this when constructing a table from keywords to display as
        part of a message object.

        :param keyword: The keyword to be rendered.
        :type keyword: str

        :param value: Value of the keyword to be rendered.
        :type value: basestring

        :param wrap_slash: Whether to replace slashes with the slash plus the
            html <wbr> tag which will help to e.g. wrap html in small cells if
            it contains a long filename. Disabled by default as it may cause
            side effects if the text contains html markup.
        :type wrap_slash: bool

        :returns: A row to be added to a messaging table.
        :rtype: safe.messaging.items.row.Row
        """
        row = m.Row()
        # Translate titles explicitly if possible
        if keyword == 'title':
            value = tr(value)
        # # See #2569
        if keyword == 'url':
            if isinstance(value, QUrl):
                value = value.toString()
        if keyword == 'date':
            if isinstance(value, QDateTime):
                value = value.toString('d MMM yyyy')
            elif isinstance(value, datetime):
                value = value.strftime('%d %b %Y')
        # we want to show the user the concept name rather than its key
        # if possible. TS
        keyword_definition = definition(keyword)
        if keyword_definition is None:
            keyword_definition = tr(keyword.capitalize().replace('_', ' '))
        else:
            try:
                keyword_definition = keyword_definition['name']
            except KeyError:
                # Handling if name is not exist.
                keyword_definition = keyword_definition['key'].capitalize()
                keyword_definition = keyword_definition.replace('_', ' ')

        # We deal with some special cases first:

        # In this case the value contains a DICT that we want to present nicely
        if keyword in [
                'value_map', 'inasafe_fields', 'inasafe_default_values'
        ]:
            value = self._dict_to_row(value)
        elif keyword == 'value_maps':
            value = self._value_maps_row(value)
        elif keyword == 'thresholds':
            value = self._threshold_to_row(value)
        # In these KEYWORD cases we show the DESCRIPTION for
        # the VALUE keyword_definition
        elif keyword in ['classification']:
            # get the keyword_definition for this class from definitions
            value = definition(value)
            value = value['description']
        # In these VALUE cases we show the DESCRIPTION for
        # the VALUE keyword_definition
        elif value in []:
            # get the keyword_definition for this class from definitions
            value = definition(value)
            value = value['description']
        # In these VALUE cases we show the NAME for the VALUE
        # keyword_definition
        elif value in [
                'multiple_event', 'single_event', 'point', 'line', 'polygon'
                'field'
        ]:
            # get the name for this class from definitions
            value = definition(value)
            value = value['name']
        # otherwise just treat the keyword as literal text
        else:
            # Otherwise just directly read the value
            value = get_string(value)

        key = m.ImportantText(keyword_definition)
        row.add(m.Cell(key))
        row.add(m.Cell(value, wrap_slash=wrap_slash))
        return row
示例#27
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.0.0

    :returns: A message object without brand element.
    :rtype: safe.messaging.message.Message
    """
    # We will store a contents section at the top for easy navigation
    table_of_contents = m.Message()
    # and this will be the main message that we create
    message = m.Message()

    _create_section_header(
        message,
        table_of_contents,
        'overview',
        tr('Overview'),
        heading_level=1)
    ##
    # Credits and disclaimers ...
    ##
    _create_section_header(
        message,
        table_of_contents,
        'disclaimer',
        tr('Disclaimer'),
        heading_level=2)
    message.add(m.Paragraph(definitions.messages.disclaimer()))

    _create_section_header(
        message,
        table_of_contents,
        'limitations',
        tr('Limitations and License'),
        heading_level=2)
    bullets = m.BulletedList()
    for item in definitions.limitations():
        bullets.add(item)
    message.add(bullets)

    ##
    # Basic concepts ...
    ##
    ##
    # Help dialog contents ...
    ##
    _create_section_header(
        message,
        table_of_contents,
        'glossary',
        tr('Glossary of terms'),
        heading_level=1)

    last_group = None
    table = None
    for key, value in list(definitions.concepts.items()):
        current_group = value['group']
        if current_group != last_group:
            if last_group is not None:
                message.add(table)
            _create_section_header(
                message,
                table_of_contents,
                current_group.replace(' ', '-'),
                current_group,
                heading_level=2)
            table = _start_glossary_table(current_group)
            last_group = current_group
        row = m.Row()
        term = value['key'].replace('_', ' ').title()
        description = m.Message(value['description'])
        for citation in value['citations']:
            if citation['text'] in [None, '']:
                continue
            if citation['link'] in [None, '']:
                description.add(m.Paragraph(citation['text']))
            else:
                description.add(m.Paragraph(
                    m.Link(citation['link'], citation['text'])))
        row.add(m.Cell(term))
        row.add(m.Cell(description))
        url = _definition_icon_url(value)
        if url:
            row.add(m.Cell(m.Image(url, **MEDIUM_ICON_STYLE)))
        else:
            row.add(m.Cell(''))
        table.add(row)
    # ensure the last group's table is added
    message.add(table)

    ##
    # Help dialog contents ...
    ##
    _create_section_header(
        message,
        table_of_contents,
        'core-functionality',
        tr('Core functionality and tools'),
        heading_level=1)

    _create_section_header(
        message,
        table_of_contents,
        'dock',
        tr('The InaSAFE Dock'),
        heading_level=2)
    message.add(dock_help())

    _create_section_header(
        message,
        table_of_contents,
        'reports',
        tr('InaSAFE Reports'),
        heading_level=2)
    message.add(report_help())

    _create_section_header(
        message,
        table_of_contents,
        'extents',
        tr('Managing analysis extents with the extents selector'),
        heading_level=2)
    message.add(extent_help())

    _create_section_header(
        message,
        table_of_contents,
        'options',
        tr('InaSAFE Options'),
        heading_level=2)
    message.add(options_help())

    _create_section_header(
        message,
        table_of_contents,
        'batch-runner',
        tr('The Batch Runner'),
        heading_level=2)
    message.add(batch_help())

    _create_section_header(
        message,
        table_of_contents,
        'osm-downloader',
        tr('The OpenStreetmap Downloader'),
        heading_level=2)
    message.add(osm_help())

    _create_section_header(
        message,
        table_of_contents,
        'petabencana-downloader',
        tr('The PetaBencana Downloader'),
        heading_level=2)
    message.add(petabencana_help())

    _create_section_header(
        message,
        table_of_contents,
        'shakemap-converter',
        tr('The Shakemap Converter'),
        heading_level=2)
    message.add(shakemap_help())

    _create_section_header(
        message,
        table_of_contents,
        'multi-buffer-tool',
        tr('The Multi Buffer Tool'),
        heading_level=2)
    message.add(multi_buffer_help())

    # Field mapping tool has a few added bits to enumerate the groups
    _create_section_header(
        message,
        table_of_contents,
        'field-mapping-tool',
        tr('The Field Mapping Tool'),
        heading_level=2)
    message.add(field_mapping_tool_help())

    _create_section_header(
        message,
        table_of_contents,
        'exposure-groups',
        tr('Exposure Groups'),
        heading_level=3)
    message.add(m.Paragraph(
        'The following demographic groups apply only to vector population '
        'exposure layers:'
    ))
    for group in population_field_groups:
        definition_to_message(
            group, message, table_of_contents, heading_level=4)

    _create_section_header(
        message,
        table_of_contents,
        'aggregation-groups',
        tr('Aggregation Groups'),
        heading_level=3)
    message.add(m.Paragraph(
        'The following demographic groups apply only to aggregation layers:'
    ))
    for group in aggregation_field_groups:
        definition_to_message(
            group, message, table_of_contents, heading_level=4)

    # End of field mapping tool help

    # Keep this last in the tool section please as it has subsections
    # and so uses the top level section style
    _create_section_header(
        message,
        table_of_contents,
        'minimum-needs',
        tr('Minimum Needs'),
        heading_level=2)
    _create_section_header(
        message,
        table_of_contents,
        'minimum-needs-tool',
        tr('The minimum needs tool'),
        heading_level=3)
    message.add(needs_help())
    _create_section_header(
        message,
        table_of_contents,
        'minimum-manager',
        tr('The minimum needs manager'),
        heading_level=3)
    message.add(needs_manager_help())

    ##
    #  Analysis workflow
    ##

    _create_section_header(
        message,
        table_of_contents,
        'analysis-steps',
        tr('Analysis steps'),
        heading_level=1)
    _create_section_header(
        message,
        table_of_contents,
        'analysis-internal-process',
        tr('Analysis internal process'),
        heading_level=2)
    analysis = definitions.concepts['analysis']
    message.add(analysis['description'])
    url = _definition_screenshot_url(analysis)
    if url:
        message.add(m.Paragraph(m.Image(url), style_class='text-center'))

    _create_section_header(
        message,
        table_of_contents,
        'analysis-progress-reporting',
        tr('Progress reporting steps'),
        heading_level=2)
    steps = list(definitions.analysis_steps.values())
    for step in steps:
        definition_to_message(
            step, message, table_of_contents, heading_level=3)

    ##
    #  Hazard definitions
    ##

    _create_section_header(
        message,
        table_of_contents,
        'hazards',
        tr('Hazard Concepts'),
        heading_level=1)

    hazard_category = definitions.hazard_category
    definition_to_message(
        hazard_category,
        message,
        table_of_contents,
        heading_level=2)

    hazards = definitions.hazards
    definition_to_message(
        hazards,
        message,
        table_of_contents,
        heading_level=2)

    ##
    #  Exposure definitions
    ##

    _create_section_header(
        message,
        table_of_contents,
        'exposures',
        tr('Exposure Concepts'),
        heading_level=1)
    exposures = definitions.exposures

    definition_to_message(
        exposures,
        message,
        table_of_contents,
        heading_level=2)

    ##
    #  Defaults
    ##

    _create_section_header(
        message,
        table_of_contents,
        'defaults',
        tr('InaSAFE Defaults'),
        heading_level=1)
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Name'), header=True))
    row.add(m.Cell(tr('Default value'), header=True))
    row.add(m.Cell(tr('Default min'), header=True))
    row.add(m.Cell(tr('Default max'), header=True))
    row.add(m.Cell(tr('Description'), header=True))
    table.add(row)
    defaults = [
        definitions.youth_ratio_default_value,
        definitions.adult_ratio_default_value,
        definitions.elderly_ratio_default_value,
        definitions.female_ratio_default_value,
        definitions.feature_rate_default_value
    ]
    for default in defaults:
        row = m.Row()
        row.add(m.Cell(default['name']))
        row.add(m.Cell(default['default_value']))
        row.add(m.Cell(default['min_value']))
        row.add(m.Cell(default['max_value']))
        row.add(m.Cell(default['description']))
        table.add(row)
    message.add(table)

    ##
    #  All Fields
    ##

    _create_section_header(
        message,
        table_of_contents,
        'all-fields',
        tr('Fields'),
        heading_level=1)
    _create_section_header(
        message,
        table_of_contents,
        'input-fields',
        tr('Input dataset fields'),
        heading_level=2)
    _create_fields_section(
        message,
        table_of_contents,
        tr('Exposure fields'),
        definitions.exposure_fields)
    _create_fields_section(
        message,
        table_of_contents,
        tr('Hazard fields'),
        definitions.hazard_fields)
    _create_fields_section(
        message,
        table_of_contents,
        tr('Aggregation fields'),
        definitions.aggregation_fields)
    _create_section_header(
        message,
        table_of_contents,
        'output-fields',
        tr('Output dataset fields'),
        heading_level=2)
    _create_fields_section(
        message,
        table_of_contents,
        tr('Impact fields'),
        definitions.impact_fields)
    _create_fields_section(
        message,
        table_of_contents,
        tr('Aggregate hazard fields'),
        definitions.aggregate_hazard_fields)
    _create_fields_section(
        message,
        table_of_contents,
        tr('Aggregation summary fields'),
        definitions.aggregation_summary_fields)
    _create_fields_section(
        message,
        table_of_contents,
        tr('Exposure summary table fields'),
        definitions.exposure_summary_table_fields)
    _create_fields_section(
        message,
        table_of_contents,
        tr('Analysis fields'),
        definitions.analysis_fields)

    ##
    #  Geometries
    ##

    _create_section_header(
        message,
        table_of_contents,
        'geometries',
        tr('Layer Geometry Types'),
        heading_level=1)
    _create_section_header(
        message,
        table_of_contents,
        'vector-geometries',
        tr('Vector'),
        heading_level=2)
    definition_to_message(
        definitions.layer_geometry_point,
        message,
        table_of_contents,
        heading_level=3)
    definition_to_message(
        definitions.layer_geometry_line,
        message,
        table_of_contents,
        heading_level=3)
    definition_to_message(
        definitions.layer_geometry_polygon,
        message,
        table_of_contents,
        heading_level=3)
    _create_section_header(
        message,
        table_of_contents,
        'raster-geometries',
        tr('Raster'),
        heading_level=2)
    definition_to_message(
        definitions.layer_geometry_raster,
        message,
        table_of_contents,
        heading_level=3)

    ##
    #  Layer Modes
    ##

    _create_section_header(
        message,
        table_of_contents,
        'layer-modes',
        tr('Layer Modes'),
        heading_level=1)
    definition_to_message(
        definitions.layer_mode,
        message,
        table_of_contents,
        heading_level=2)

    ##
    #  Layer Purposes
    ##

    _create_section_header(
        message,
        table_of_contents,
        'layer-purposes',
        tr('Layer Purposes'),
        heading_level=1)
    definition_to_message(
        definitions.layer_purpose_hazard,
        message,
        table_of_contents,
        heading_level=2)
    definition_to_message(
        definitions.layer_purpose_exposure,
        message,
        table_of_contents,
        heading_level=2)
    definition_to_message(
        definitions.layer_purpose_aggregation,
        message,
        table_of_contents,
        heading_level=2)
    definition_to_message(
        definitions.layer_purpose_exposure_summary,
        message,
        table_of_contents,
        heading_level=2)
    definition_to_message(
        definitions.layer_purpose_aggregate_hazard_impacted,
        message,
        table_of_contents,
        heading_level=2)
    definition_to_message(
        definitions.layer_purpose_aggregation_summary,
        message,
        table_of_contents,
        heading_level=2)
    definition_to_message(
        definitions.layer_purpose_exposure_summary_table,
        message,
        table_of_contents,
        heading_level=2)
    definition_to_message(
        definitions.layer_purpose_profiling,
        message,
        table_of_contents,
        heading_level=2)

    ##
    # All units
    ##

    _create_section_header(
        message,
        table_of_contents,
        'all-units',
        tr('All Units'),
        heading_level=1)
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Name'), header=True))
    row.add(m.Cell(tr('Plural'), header=True))
    row.add(m.Cell(tr('Abbreviation'), header=True))
    row.add(m.Cell(tr('Details'), header=True))
    table.add(row)
    for unit in definitions.units_all:
        row = m.Row()
        row.add(m.Cell(unit['name']))
        row.add(m.Cell(unit['plural_name']))
        row.add(m.Cell(unit['abbreviation']))
        row.add(m.Cell(unit['description']))
        table.add(row)
    message.add(table)

    ##
    #  Post processors
    ##

    _create_section_header(
        message,
        table_of_contents,
        'post-processors',
        tr('Post Processors'),
        heading_level=1)
    _create_section_header(
        message,
        table_of_contents,
        'post-processor-input-types',
        tr('Post Processor Input Types'),
        heading_level=2)
    table = _create_post_processor_subtable(
        post_processor_input_types
    )
    message.add(table)

    _create_section_header(
        message,
        table_of_contents,
        'post-processor-input-values',
        tr('Post Processor Input Values'),
        heading_level=2)
    table = _create_post_processor_subtable(
        post_processor_input_values
    )
    message.add(table)

    _create_section_header(
        message,
        table_of_contents,
        'post-processor-process-values',
        tr('Post Processor Process Types'),
        heading_level=2)
    table = _create_post_processor_subtable(
        safe.processors.post_processor_process_types
    )
    message.add(table)

    _create_section_header(
        message,
        table_of_contents,
        'post-processors',
        tr('Post Processors'),
        heading_level=2)
    post_processors = safe.processors.post_processors
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Name'), header=True))
    row.add(m.Cell(tr('Input Fields'), header=True))
    row.add(m.Cell(tr('Output Fields'), header=True))
    table.add(row)
    for post_processor in post_processors:
        row = m.Row()
        row.add(m.Cell(post_processor['name']))
        # Input fields
        bullets = m.BulletedList()
        for key, value in sorted(post_processor['input'].items()):
            bullets.add(key)
        row.add(m.Cell(bullets))
        # Output fields
        bullets = m.BulletedList()
        for key, value in sorted(post_processor['output'].items()):
            name = value['value']['name']
            formula_type = value['type']['key']
            if formula_type == 'formula':
                formula = value['formula']
            else:
                # We use python introspection because the processor
                # uses a python function for calculations
                formula = value['function'].__name__
                formula += ' ('
                formula += value['function'].__doc__
                formula += ')'
            bullets.add('%s  %s. : %s' % (
                name, formula_type, formula))

        row.add(m.Cell(bullets))
        table.add(row)
        # Add the descriptions
        row = m.Row()
        row.add(m.Cell(''))
        row.add(m.Cell(post_processor['description'], span=2))
        table.add(row)
    message.add(table)

    ##
    # Reporting
    ##
    _create_section_header(
        message,
        table_of_contents,
        'reporting',
        tr('Reporting'),
        heading_level=1)

    paragraph = m.Paragraph(
        m.ImportantText(tr('Note: ')),
        m.Text(tr(
            'This section of the help documentation is intended for advanced '
            'users who want to modify reports which are produced by InaSAFE.'
        )))
    message.add(paragraph)
    _create_section_header(
        message,
        table_of_contents,
        'reporting-overview',
        tr('Overview'),
        heading_level=2)
    message.add(m.Paragraph(tr(
        'Whenever InaSAFE completes an analysis, it will automatically '
        'generate a number of reports. Some of these reports are based on '
        'templates that are shipped with InaSAFE, and can be customised or '
        'over-ridden by creating your own templates. The following '
        'reports are produced in InaSAFE:'
    )))
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Name'), header=True))
    row.add(m.Cell(tr('Customisable?'), header=True))
    row.add(m.Cell(tr('Example'), header=True))
    row.add(m.Cell(tr('Description'), header=True))
    table.add(row)

    for report in all_reports:
        row = m.Row()
        row.add(m.Cell(report['name']))
        if report['customisable']:
            row.add(m.Cell(tr('Yes')))
        else:
            row.add(m.Cell(tr('No')))
        png_image_path = resources_path(
            'img', 'screenshots', report['thumbnail'])
        row.add(m.Image(png_image_path, style_class='text-center'))
        row.add(m.Cell(report['description']))
        table.add(row)

    message.add(table)

    message.add(m.Paragraph(tr(
        'In the sections that follow, we provide more technical information '
        'about the custom QGIS Expressions and special template elements '
        'that can be used to customise your templates.'
    )))

    _create_section_header(
        message,
        table_of_contents,
        'reporting-expressions',
        tr('QGIS Expressions'),
        heading_level=2)
    message.add(m.Paragraph(tr(
        'InaSAFE adds a number of expressions that can be used to '
        'conveniently obtain provenance data to the active analysis results. '
        'The expressions can also be used elsewhere in QGIS as needed.'
        '.'
    )))

    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('Name'), header=True))
    row.add(m.Cell(tr('Description'), header=True))
    table.add(row)
    for expression_name, expression in sorted(qgis_expressions().items()):
        row = m.Row()
        row.add(m.Cell(expression_name))
        help = expression.helptext()
        # This pattern comes from python/qgis/core/__init__.py ≈ L79
        pattern = r'<h3>(.*) function</h3><br>'
        help = re.sub(pattern, '', help)
        help = re.sub(r'\n', '<br>', help)
        row.add(m.Cell(help))
        table.add(row)
    message.add(table)

    _create_section_header(
        message,
        table_of_contents,
        'reporting-composer-elements',
        tr('Composer Elements'),
        heading_level=2)
    message.add(m.Paragraph(tr(
        'InaSAFE looks for elements with specific id\'s on the composer '
        'page and replaces them with InaSAFE specific content.'
    )))
    table = m.Table(style_class='table table-condensed table-striped')
    row = m.Row()
    row.add(m.Cell(tr('ID'), header=True))
    row.add(m.Cell(tr('Description'), header=True))
    table.add(row)
    for item in html_frame_elements:
        row = m.Row()
        row.add(m.Cell(item['id']))
        row.add(m.Cell(item['description']))
        table.add(row)
    message.add(table)

    ##
    # Developer documentation
    ##
    _create_section_header(
        message,
        table_of_contents,
        'developer-guide',
        tr('Developer Guide'),
        heading_level=1)
    message.add(developer_help())

    # Finally we add the table of contents at the top
    full_message = m.Message()
    # Contents is not a link so reset style
    style = SECTION_STYLE
    style['element_id'] = ''
    header = m.Heading(tr('Contents'), **style)
    full_message.add(header)
    full_message.add(table_of_contents)
    full_message.add(message)
    return full_message
示例#28
0
    def _threshold_to_row(thresholds_keyword):
        """Helper to make a message row from a threshold

        We are expecting something like this:

        {
            'thresholds': {
                'structure': {
                    'ina_structure_flood_hazard_classification': {
                        'classes': {
                            'low': [1, 2],
                            'medium': [3, 4],
                            'high': [5, 6]
                        },
                        'active': True
                    },
                    'ina_structure_flood_hazard_4_class_classification':
                    {
                        'classes': {
                            'low': [1, 2],
                            'medium': [3, 4],
                            'high': [5, 6],
                            'very_high': [7, 8]
                        },
                        'active': False

                    }
                },
                'population': {
                    'ina_population_flood_hazard_classification': {
                        'classes': {
                            'low': [1, 2.5],
                            'medium': [2.5, 4.5],
                            'high': [4.5, 6]
                        },
                        'active': False
                    },
                    'ina_population_flood_hazard_4_class_classification':
                    {
                        'classes': {
                            'low': [1, 2.5],
                            'medium': [2.5, 4],
                            'high': [4, 6],
                            'very_high': [6, 8]
                        },
                        'active': True
                    }
                },
            },

        Each value is a list with exactly two element [a, b], where a <= b.

        :param thresholds_keyword: Value of the keyword to be rendered. This
            must be a string representation of a dict, or a dict.
        :type thresholds_keyword: basestring, dict

        :returns: A table to be added into a cell in the keywords table.
        :rtype: safe.messaging.items.table
        """
        if isinstance(thresholds_keyword, basestring):
            thresholds_keyword = literal_eval(thresholds_keyword)

        for k, v in thresholds_keyword.items():
            # If the v is not dictionary, it should be the old value maps.
            # To handle thresholds in the Impact Function.
            if not isinstance(v, dict):
                table = m.Table(style_class='table table-condensed')

                for key, value in thresholds_keyword.items():
                    row = m.Row()
                    name = definition(key)['name'] if definition(key) else key
                    row.add(m.Cell(m.ImportantText(name)))
                    pretty_value = tr('%s to %s' % (value[0], value[1]))
                    row.add(m.Cell(pretty_value))

                    table.add(row)
                return table

        table = m.Table(style_class='table table-condensed table-striped')

        i = 0
        for exposure_key, classifications in thresholds_keyword.items():
            i += 1
            exposure = definition(exposure_key)
            exposure_row = m.Row()
            exposure_row.add(m.Cell(m.ImportantText('Exposure')))
            exposure_row.add(m.Cell(m.Text(exposure['name'])))
            exposure_row.add(m.Cell(''))
            table.add(exposure_row)

            active_classification = None
            classification_row = m.Row()
            classification_row.add(m.Cell(m.ImportantText('Classification')))
            for classification, value in classifications.items():
                if value.get('active'):
                    active_classification = definition(classification)
                    classification_row.add(
                        m.Cell(active_classification['name']))
                    classification_row.add(m.Cell(''))
                    break

            if not active_classification:
                classification_row.add(m.Cell(tr('No classifications set.')))
                classification_row.add(m.Cell(''))
                continue

            table.add(classification_row)

            header = m.Row()
            header.add(m.Cell(tr('Class name')))
            header.add(m.Cell(tr('Minimum')))
            header.add(m.Cell(tr('Maximum')))
            table.add(header)
            classes = active_classification.get('classes')
            # Sort by value, put the lowest first
            classes = sorted(classes, key=lambda k: k['value'])
            for the_class in classes:
                threshold = classifications[
                    active_classification['key']]['classes'][the_class['key']]
                row = m.Row()
                row.add(m.Cell(the_class['name']))
                row.add(m.Cell(threshold[0]))
                row.add(m.Cell(threshold[1]))
                table.add(row)

            if i < len(thresholds_keyword):
                # Empty row
                empty_row = m.Row()
                empty_row.add(m.Cell(''))
                empty_row.add(m.Cell(''))
                table.add(empty_row)

        return table
示例#29
0
def check_memory_usage(buffered_geo_extent, cell_size):
    """Helper to check if analysis is feasible when extents change.

    For simplicity, we will do all our calculations in geocrs.

    :param buffered_geo_extent: An extent in the for [xmin, ymin, xmax, ymax]
    :type buffered_geo_extent: list

    :param cell_size: The size of a cell (assumes in the X direction).
    :type cell_size: float

    :returns: True if it appears we have enough memory (or we can't compute
        it), False if it appears we do not have enough.
    :rtype: bool

    :raises: A Message containing notes about how much memory is needed
        for a single raster and if this is likely to result in an error.

    :returns: True if it is supposed that there is sufficient memory,
        False if it is supposed that too little memory exists.
    :rtype: bool
    """
    message = m.Message()
    check_heading = m.Heading(tr('Checking available memory'),
                              **PROGRESS_UPDATE_STYLE)
    message.add(check_heading)

    width = buffered_geo_extent[2] - buffered_geo_extent[0]
    height = buffered_geo_extent[3] - buffered_geo_extent[1]
    try:
        # noinspection PyAugmentAssignment
        width = width / cell_size
        # noinspection PyAugmentAssignment
        height = height / cell_size
    except TypeError:
        # Could have been a vector layer for example
        reason = tr(
            'Computed cellsize was None. Memory check currently only works '
            'for raster input layers.')
        message.add(reason)
        send_dynamic_message(dispatcher.Anonymous, message)
        return True  # assume enough mem since we have no vector check logic

    bullet_list = m.BulletedList()
    bullet = m.Paragraph(m.ImportantText(tr('Width: ')), str(width))
    bullet_list.add(bullet)
    bullet = m.Paragraph(m.ImportantText(tr('Height: ')), str(height))
    bullet_list.add(bullet)
    bullet = m.Paragraph(m.ImportantText(tr('Cell Size: ')), str(cell_size))
    bullet_list.add(bullet)
    message.add(bullet_list)

    # Compute mem requirement in MB (assuming numpy uses 8 bytes by per
    # cell) see this link:
    # http://stackoverflow.com/questions/11784329/
    #      python-memory-usage-of-numpy-arrays
    # Also note that the on-disk requirement of the clipped tifs is about
    # half this since the tifs as in single precision,
    # whereas numpy arrays are in double precision.
    requirement = ((width * height * 8) / 1024 / 1024)
    try:
        free_memory = get_free_memory()
    except ValueError:
        error_heading = m.Heading(tr('Memory check error'), **WARNING_STYLE)
        error_message = tr('Could not determine free memory')
        message.add(error_heading)
        message.add(error_message)
        send_dynamic_message(dispatcher.Anonymous, message)
        LOGGER.exception(message)
        return True  # still let the user try to run their analysis

    # We work on the assumption that if more than 10% of the available
    # memory is occupied by a single layer we could run out of memory
    # (depending on the impact function). This is because multiple
    # in memory copies of the layer are often made during processing.
    warning_limit = 10
    usage_indicator = (float(requirement) / float(free_memory)) * 100
    counts_message = tr('Memory requirement: about %d mb per raster layer ('
                        '%d mb available)') % (requirement, free_memory)
    usage_message = tr('Memory used / available: %d/%d') % (usage_indicator,
                                                            warning_limit)
    message.add(counts_message)
    message.add(usage_message)

    if warning_limit <= usage_indicator:
        warning_heading = m.Heading(tr('Potential memory issue'),
                                    **WARNING_STYLE)
        warning_message = tr(
            'There may not be enough free memory to run this analysis. You can'
            ' attempt to run the analysis anyway, but note that your computer '
            'may become unresponsive during execution, and / or the analysis '
            'may fail due to insufficient memory. Proceed at your own risk.')
        suggestion_heading = m.Heading(tr('Suggestion'), **SUGGESTION_STYLE)
        suggestion = tr(
            'Try zooming in to a smaller area or using a raster layer with a '
            'coarser resolution to speed up execution and reduce memory '
            'requirements. You could also try adding more RAM to your '
            'computer.')

        message.add(warning_heading)
        message.add(warning_message)
        message.add(suggestion_heading)
        message.add(suggestion)
        send_dynamic_message(dispatcher.Anonymous, message)
        # LOGGER.info(message.to_text())
        return False

    send_dynamic_message(dispatcher.Anonymous, message)
    # LOGGER.info(message.to_text())
    return True
示例#30
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/'
                                    'minimum-needs-screenshot.png' %
                                    resources_path()),
                            style_class='text-center')
    message.add(paragraph)
    message.add(
        m.Paragraph(
            tr('During and after a disaster, providing for the basic human minimum '
               'needs of food, water, hygiene and shelter is an important element of '
               'your contingency plan. InaSAFE has a customisable minimum needs '
               'system that allows you to define country or region specific '
               'requirements for compiling a needs report where the exposure '
               'layer represents population.')))
    message.add(
        m.Paragraph(
            tr('By default InaSAFE uses minimum needs defined for Indonesia - '
               'and ships with additional profiles for the Philippines and Tanzania. '
               'You can customise these or add your own region-specific profiles too.'
               )))
    message.add(
        m.Paragraph(
            tr('Minimum needs are grouped into regional or linguistic \'profiles\'. '
               'The default profile is \'BNPB_en\' - the english profile for the '
               'national disaster agency in Indonesia. '
               'You will see that this profile defines requirements for displaced '
               'persons in terms of Rice, Drinking Water, Clean Water (for bathing '
               'etc.), Family Kits (with personal hygiene items) and provision of '
               'toilets.')))
    message.add(
        m.Paragraph(
            tr('Each item in the profile can be customised or removed. For example '
               'selecting the first item in the list and then clicking on the '
               '\'pencil\' icon will show the details of how it was defined. '
               'If you scroll up and down in the panel you will see that for each '
               'item, you can set a name, description, units (in singular, '
               'plural and abbreviated forms), specify maxima and minima for the '
               'quantity of item allowed, a default and a frequency. You would use '
               'the maxima and minima to ensure that disaster managers never '
               'allocate amounts that will not be sufficient for human livelihood, '
               'and also that will not overtax the logistics operation for those '
               'providing humanitarian relief.')))
    message.add(
        m.Paragraph(
            tr('The final item in the item configuration is the \'readable '
               'sentence\' which bears special discussion. Using a simple system of '
               'tokens you can construct a sentence that will be used in the '
               'generated needs report.')))
    message.add(m.Heading(tr('Minimum needs profiles'), **INFO_STYLE))
    message.add(
        m.Paragraph(
            tr('A profile is a collection of resources that define the minimum needs '
               'for a particular country or region. Typically a profile should be '
               'based on a regional, national or international standard. The '
               'actual definition of which resources are needed in a given '
               'profile is dependent on the local conditions and customs for the '
               'area where the contingency plan is being devised.')))
    message.add(
        m.Paragraph(
            tr('For example in the middle east, rice is a staple food whereas in '
               'South Africa, maize meal is a staple food and thus the contingency '
               'planning should take these localised needs into account.')))

    message.add(m.Heading(tr('Minimum needs resources'), **INFO_STYLE))
    message.add(
        m.Paragraph(
            tr('Each item in a minimum needs profile is a resource. Each resource '
               'is described as a simple natural language sentence e.g.:')))

    message.add(
        m.EmphasizedText(
            tr('Each person should be provided with 2.8 kilograms of Rice weekly.'
               )))
    message.add(
        m.Paragraph(
            tr('By clicking on a resource entry in the profile window, and then '
               'clicking the black pencil icon you will be able to edit the '
               'resource using the resource editor. Alternatively you can create a '
               'new resource for a profile by clicking on the black + icon in '
               'the profile manager. You can also remove any resource from a '
               'profile using the - icon in the profile manager.')))

    message.add(m.Heading(tr('Resource Editor'), **INFO_STYLE))
    message.add(
        m.Paragraph(
            tr('When switching to edit or add resource mode, the minimum needs '
               'manager will be updated to show the resource editor. Each '
               'resource is described in terms of:')))
    bullets = m.BulletedList()
    bullets.add(
        m.Text(m.ImportantText(tr('resource name')), tr(' - e.g. Rice')))
    bullets.add(
        m.Text(m.ImportantText(tr('a description of the resource')),
               tr(' - e.g. Basic food')))
    bullets.add(
        m.Text(m.ImportantText(tr('unit in which the resource is provided')),
               tr(' - e.g. kilogram')))
    bullets.add(
        m.Text(m.ImportantText(tr('pluralised form of the units')),
               tr(' - e.g. kilograms')))
    bullets.add(
        m.Text(m.ImportantText(tr('abbreviation for the unit')),
               tr(' - e.g. kg')))
    bullets.add(
        m.Text(
            m.ImportantText(tr('the default allocation for the resource')),
            tr(' - e.g. 2.8. This number can be overridden on a '
               'per-analysis basis')))
    bullets.add(
        m.Text(
            m.ImportantText(
                tr('minimum allowed which is used to prevent allocating')),
            tr(' - e.g. no drinking water to displaced persons')))
    bullets.add(
        m.ImportantText(
            tr('maximum allowed which is used to set a sensible upper '
               'limit for the resource')))
    bullets.add(
        m.ImportantText(
            tr('a readable sentence which is used to compile the '
               'sentence describing the resource in reports.')))
    message.add(bullets)

    message.add(
        m.Paragraph(
            tr('These parameters are probably all fairly self explanatory, but '
               'the readable sentence probably needs further detail. The '
               'sentence is compiled using a simple keyword token replacement '
               'system. The following tokens can be used:')))

    bullets = m.BulletedList()
    bullets.add(m.Text('{{ Default }}'))
    bullets.add(m.Text('{{ Unit }}'))
    bullets.add(m.Text('{{ Units }}'))
    bullets.add(m.Text('{{ Unit abbreviation }}'))
    bullets.add(m.Text('{{ Resource name }}'))
    bullets.add(m.Text('{{ Frequency }}'))
    bullets.add(m.Text('{{ Minimum allowed }}'))
    bullets.add(m.Text('{{ Maximum allowed }}'))
    message.add(bullets)

    message.add(
        m.Paragraph(
            tr('When the token is placed in the sentence it will be replaced with '
               'the actual value at report generation time. This contrived example '
               'shows a tokenised sentence that includes all possible keywords:'
               )))

    message.add(
        m.EmphasizedText(
            tr('A displaced person should be provided with {{ %s }} '
               '{{ %s }}/{{ %s }}/{{ %s }} of {{ %s }}. Though no less than {{ %s }} '
               'and no more than {{ %s }}. This should be provided {{ %s }}.' %
               ('Default', 'Unit', 'Units', 'Unit abbreviation',
                'Resource name', 'Minimum allowed', 'Maximum allowed',
                'Frequency'))))
    message.add(
        m.Paragraph(tr('Would generate a human readable sentence like this:')))

    message.add(
        m.ImportantText(
            tr('A displaced person should be provided with 2.8 kilogram/kilograms/kg '
               'of rice. Though no less than 0 and no more than 100. This should '
               'be provided daily.')))
    message.add(
        m.Paragraph(
            tr('Once you have populated the resource elements, click the Save '
               'resource button to return to the profile view. You will see the '
               'new resource added in the profile\'s resource list.')))

    message.add(m.Heading(tr('Managing profiles'), **INFO_STYLE))
    message.add(
        m.Paragraph(
            tr('In addition to the profiles that come as standard with InaSAFE, you '
               'can create new ones, either from scratch, or based on an existing '
               'one (which you can then modify).')))
    message.add(
        m.Paragraph(
            tr('Use the New button to create new profile. When prompted, give your '
               'profile a name e.g. \'JakartaProfile\'.')))
    message.add(
        m.Paragraph(
            tr('Note: The profile must be saved in your home directory under '
               '(QGIS profile path)/minimum_needs in order '
               'for InaSAFE to successfully '
               'detect it.')))
    message.add(
        m.Paragraph(
            tr('An alternative way to create a new profile is to use the Save as to '
               'clone an existing profile. The clone profile can then be edited '
               'according to your specific needs.')))
    message.add(m.Heading(tr('Active profile'), **INFO_STYLE))
    message.add(
        m.Paragraph(
            tr('It is important to note, that which ever profile you select in the '
               'Profile pick list, will be considered active and will be used as '
               'the basis for all minimum needs analysis. You need to restart '
               'QGIS before the changed profile become active.')))
    return message