Textual Definitions Automated Check

Discussion on this check can be found here.

Requirements

  1. Each definition must be unique.
  2. Each entity must not have more than one textual definition.
  3. Each entity should have a textual definition using IAO:0000115 (definition).

Fixes

Uniqueness

Update each duplicate definition to have some detail that differentiates one term from another.

Multiples

If a term has more than one defintion, combine the two definitions. Alternatively, change one definition to an rdfs:comment if it just contains further details.

Missing Definitions

Add an IAO:0000115 (definition) annotation to each term that is missing a definition. For help writing good definitions, see Textual Definitions Recommendations.

For adding defintions in bulk, check out ROBOT template.

Implementation

ROBOT report is run over the ontology. A count of violations for each of the following checks is retrieved from the report object: duplicate definition, multiple definitions, and missing definition. If there are any duplicate or multiple defintions, it is an error. If there are missing definitions, it is a warning.

import dash_utils
from dash_utils import format_msg


def has_valid_definitions(report):
   """Check fp 6 - textual definitions.

   If the ontology passes all ROBOT report definition checks, PASS. If there
   are any violations, return that level of violation and a summary of the
   violations.

   Args:
       report (Report): ROBOT report object
   """
   if report is None:
       return {'status': 'INFO',
               'comment': 'ROBOT Report could not be generated'}

   # error level violations
   duplicates = report.getViolationCount('duplicate_definition')
   multiples = report.getViolationCount('multiple_definitions')

   # warn level violation
   missing = report.getViolationCount('missing_definition')

   if duplicates > 0 and multiples > 0 and missing > 0:
       return {'status': 'ERROR',
               'comment': ' '.join([duplicate_msg.format(duplicates),
                                    multiple_msg.format(multiples),
                                    missing_msg.format(missing),
                                    help_msg])}
   elif duplicates > 0 and multiples > 0:
       return {'status': 'ERROR',
               'comment': ' '.join([duplicate_msg.format(duplicates),
                                    multiple_msg.format(multiples),
                                    help_msg])}
   elif duplicates > 0 and missing > 0:
       return {'status': 'ERROR',
               'comment': ' '.join([duplicate_msg.format(duplicates),
                                    missing_msg.format(missing),
                                    help_msg])}
   elif multiples > 0 and missing > 0:
       return {'status': 'ERROR',
               'comment': ' '.join([multiple_msg.format(multiples),
                                    missing_msg.format(missing),
                                    help_msg])}
   elif duplicates > 0:
       return {'status': 'ERROR',
               'comment': ' '.join([duplicate_msg.format(duplicates),
                                    help_msg])}
   elif multiples > 0:
       return {'status': 'ERROR',
               'comment': ' '.join([multiple_msg.format(missing),
                                    help_msg])}
   elif missing > 0:
       return {'status': 'WARN',
               'comment': ' '.join([missing_msg.format(missing),
                                    help_msg])}
   else:
       # no violations found
       return {'status': 'PASS'}


# violation messages
duplicate_msg = '{0} duplicate definitions.'
multiple_msg = '{0} multiple definitions.'
missing_msg = '{0} missing definitions.'
help_msg = 'See ROBOT Report for details.'