diff --git a/docs/user-guide/load-ontology.rst b/docs/user-guide/load-ontology.rst index 7c41f83..3d3be87 100644 --- a/docs/user-guide/load-ontology.rst +++ b/docs/user-guide/load-ontology.rst @@ -11,29 +11,35 @@ JSON file which is available for download from the `HPO website >> 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: @@ -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 @@ -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. @@ -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:: diff --git a/docs/user-guide/sort-term-ids.rst b/docs/user-guide/sort-term-ids.rst index 56af6b7..fa7603c 100644 --- a/docs/user-guide/sort-term-ids.rst +++ b/docs/user-guide/sort-term-ids.rst @@ -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 diff --git a/docs/user-guide/validate-phenotypic-features.rst b/docs/user-guide/validate-phenotypic-features.rst index 46a7f73..05bbc16 100644 --- a/docs/user-guide/validate-phenotypic-features.rst +++ b/docs/user-guide/validate-phenotypic-features.rst @@ -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=, category='obsolete_term_id_is_used', message='Using the obsolete HP:0001505 instead of HP:0001166 for Arachnodactyly') + ValidationResult(level=, 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. diff --git a/src/hpotk/validate/_model.py b/src/hpotk/validate/_model.py index c55dc18..06a9b3b 100644 --- a/src/hpotk/validate/_model.py +++ b/src/hpotk/validate/_model.py @@ -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: """