Skip to content

Commit

Permalink
Merge branch 'update-guides' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
ielis committed Dec 5, 2023
2 parents 511b4cd + 62b9566 commit d6d421d
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 24 deletions.
49 changes: 30 additions & 19 deletions docs/user-guide/load-ontology.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,35 @@ JSON file which is available for download from the `HPO website <https://hpo.jax
Minimal ontology
^^^^^^^^^^^^^^^^

Let's load HPO:
Let's load the HPO version released on Oct 9th, 2023:

.. doctest:: load-minimal-ontology

>>> import hpotk

>>> hpo = hpotk.load_minimal_ontology('data/hp.toy.json')
>>> hpo.version
'2022-10-05'
>>> url = 'https://github.com/obophenotype/human-phenotype-ontology/releases/download/v2023-10-09/hp.json'
>>> hpo = hpotk.load_minimal_ontology(url)

We load the ontology from a toy Obographs JSON file and we check the version of the data.
The loader fetches the Obographs JSON file and loads the data into :class:`hpotk.ontology.MinimalOntology`.

.. note::

The loader can fetch the HPO from a URL, and it transparently handles gzipped files
if the file name ends with `.gz` suffix.

Now, we can check that the toy HPO has 393 primary terms:
Having `MinimalOntology`, we can do several checks. We can check the HPO version:

.. doctest:: load-minimal-ontology

>>> hpo.version
'2023-10-09'

check that the Oct 9th release has *17,664* terms:

.. doctest:: load-minimal-ontology

>>> len(hpo)
393
17664

check that `HP:0001250` is/was a valid identifier:

Expand All @@ -54,18 +60,22 @@ or print names of its children in alphabetical order:

.. doctest:: load-minimal-ontology

>>> children_names = sorted(
... map(lambda ch: hpo.get_term(ch).name,
... hpo.graph.get_children(seizure)))
>>> for child in children_names:
>>> for child in sorted(hpo.get_term_name(child)
... for child in hpo.graph.get_children(seizure)):
... print(child)
Bilateral tonic-clonic seizure
Dialeptic seizure
Focal-onset seizure
Generalized-onset seizure
Infection-related seizure
Maternal seizure
Motor seizure

.. note::

The toy HPO is a subset of the full HPO and Seizure only 2 child terms in the toy file. There are more children
in the real-life ("production") HPO.
Neonatal seizure
Nocturnal seizures
Non-motor seizure
Reflex seizure
Status epilepticus
Symptomatic seizures

The terms of :class:`hpotk.ontology.MinimalOntology` are instances of :class:`hpotk.model.MinimalTerm` and contain a subset
of the term metadata such as identifier, labels, and alternative IDs. The simplified are useful for tasks that
Expand All @@ -80,12 +90,13 @@ loader function:
.. testsetup:: load-ontology

import hpotk
url = 'https://github.com/obophenotype/human-phenotype-ontology/releases/download/v2023-10-09/hp.json'

.. doctest:: load-ontology

>>> hpo = hpotk.load_ontology('data/hp.toy.json')
>>> hpo = hpotk.load_ontology(url)
>>> hpo.version
'2022-10-05'
'2023-10-09'

Same as above, the loader parses the Obographs JSON file and returns an ontology. However, this time
it is an instance :class:`hpotk.ontology.Ontology` with :class:`hpotk.model.Term` - the term with full metadata.
Expand All @@ -104,9 +115,9 @@ or check out seizure's synonyms:

>>> for synonym in seizure.synonyms:
... print(synonym.name)
Epileptic seizure
Seizures
Epilepsy
Epileptic seizure

.. note::

Expand Down
10 changes: 9 additions & 1 deletion docs/user-guide/sort-term-ids.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,15 @@ And sort the HPO terms:
>>> indices = sorting.argsort(term_ids)
>>> ordered = tuple(term_ids[idx] for idx in indices)

Now let's look at the order:
Now let's look at the order. Originally, the HPO terms were ordered as follows::

'HP:0001744' # Splenomegaly
'HP:0020221' # Clonic seizure
'HP:0001238' # Slender finger
'HP:0011153' # Focal motor seizure
'HP:0002240' # Hepatomegaly

When sorted, we get this order:

.. doctest:: sort-term-ids

Expand Down
26 changes: 25 additions & 1 deletion docs/user-guide/validate-phenotypic-features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,28 @@ There seems to an issue. Let's break it down:
The validator points out that *Seizure* is an ancestor of *Focal clonic seizure* and should, therefore, not be used
as an annotation of the individual.

That's it for now. There are more validators to come!
Validation pipeline
^^^^^^^^^^^^^^^^^^^

For greater convenience, the validators can be integrated and run on the input at the same time:

.. doctest:: check-consistency

>>> from hpotk.validate import ValidationRunner

>>> # Create a validation runner
>>> runner = ValidationRunner(validators=(obs_val, pa_val, ap_val))

>>> # Validate the input features
>>> vr = runner.validate_all(term_ids)
>>> vr.is_ok()
False

>>> for validation_result in vr.results:
... print(validation_result)
ValidationResult(level=<ValidationLevel.WARNING: 1>, category='obsolete_term_id_is_used', message='Using the obsolete HP:0001505 instead of HP:0001166 for Arachnodactyly')
ValidationResult(level=<ValidationLevel.ERROR: 2>, category='annotation_propagation', message='Terms should not contain both present Focal clonic seizure [HP:0002266] and its present or excluded ancestor Seizure [HP:0001250]')

:class:`hpotk.validate.ValidationRunner` applies several validators and aggregates the issues into
:class:`hpotk.validate.ValidationResults`. We can check if the input passed the validation and if not, we can go through
the issues.
6 changes: 3 additions & 3 deletions src/hpotk/validate/_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,11 @@ class ValidationRunner:
The runner applies a sequence of rule validators on items and packs the results
into :class:`ValidationResults`.
:param validators: a sequence of :class:`RuleValidator`\ s to apply.
:param validators: an iterable of :class:`RuleValidator`\ s to apply.
"""

def __init__(self, validators: typing.Sequence[RuleValidator]):
self._validators = validators
def __init__(self, validators: typing.Iterable[RuleValidator]):
self._validators = tuple(validators)

def validate_all(self, items: typing.Sequence[typing.Union[Identified, TermId]]) -> ValidationResults:
"""
Expand Down

0 comments on commit d6d421d

Please sign in to comment.