Releases: ontology-tools/py-horned-owl
v1.0.2
v1.0.1
v1.0.1.dev1
v1.0.0
What's Changed
- Support for horned-owl 1.0.0
- More convenience functions to create components
- Better support for CURIEs in all places
- Adding ofn read support. by @cmungall in #19
- Add load and save serialization options by @b-gehrke in #20
New Contributors
Full Changelog: v0.3.2...v1.0.0
v0.3.2
v0.3.1
What's Changed
- Added proper conversions for references. Thus fixing infinite recursion in
get_axioms_for_iri
function.
Full Changelog: v0.3.0...v0.3.1
v0.3.0
What's Changed
Overview - rust native types
Prior to version 0.3.0 axioms and other data types were expressed as S-Expressions-like lists of strings and converted to horned-owl types in rust. With the new version, local rust types (thin wrappers around horned-owl types) are exported directly, allowing a more pythonic way of interacting with the horned owl library. For example, consider the axiom
Class: Child
SubClassOf: has_parent some Human
This axiom was previously written as
[
'SubClassOf',
':Child',
[
'ObjectSomeValuesFrom',
':has_parent', 'Human'
]
]
Now it is written as
SubClassOf(
Class(IRI.parse(':Child')),
ObjectSomeValuesFrom(
ObjectProperty(IRI.parse(':has_parent')),
Class(IRI.parse(':Human'))
)
)
In contrast to the S-Expression way, we now use proper types and classes. Datatypes can be created by invoking their constructor or (in case of IRI
) their factory method. This does not only improve the readability but also allows type checkers to spot problems.
Type support
In addition to the types theirselves, version 0.3.0 adds python stubs for all classes, their fields and methods, and other functions. They can be used up by language servers and IDEs to further improve the developer experience.
Instance checking
With native rust types being exposed as python classes checking which kind of axiom or class expression is now as easy as checking the runtime type of any other python type using isinstanceof
.
Completeness
While previously the conversation between rust and python objects was implemented manually for only a subset of all types in version 0.3.0 the conversion logic is generated by macros for each datatype. Hence, all datatypes occuring in an ontology are now accessible and manipulatable from python.
Performance
A quick comparison of performance shows major improvements in interacting with axioms: For this test, the chebi_core
ontology was loaded (three times and then averaged). Then, the number of axioms was counted by iteration over all axioms in the ontology. Lastly 100.000 axioms were added to an empty ontology. Additionally, the performance of horned-owl was recorded as a baseline. Below are the performance results.
Task | 0.2.2 | 0.3.0 | horned-owl |
---|---|---|---|
Loading chebi | 26.2704s | 27.5580s | 9.9989s |
Iterating axioms | 2.7132s | 1.1928s | 3.6232 |
Adding 100.000 axioms | 4.3871s | 0.6688s | 0.04929ms |
It is unclear, why iterating all axioms is slower in native horned-owl.
Alternative approache using JSON or other serializations
Using other serializations like serde(-json) would require creating similar wrappers as now with pyo3. Furthermore, to add the same level of type support, python classes and functions would have to be created or generated to serialize and deserialize on the python side.
Examples
import pyhornedowl
from pyhornedowl.model import *
filename = "/path/to/ontology.owl"
onto = pyhornedowl.open_ontology(filename) # open and load an ontology
classes = onto.get_classes() # get all defined classes
axioms = onto.get_axioms() # get all axioms
axiom = SubClassOf(Class(onto.iri("http://example.com/A")), Class(onto.iri('http://example.com/B'))) # define a new axiom
onto.add_axiom(axiom) # add axiom to ontology
subclassaxioms = [a for a in axioms if isinstance(a.axiom, SubClassOf)] # get all SubClassOf axioms
Full Changelog: v0.2.2...v0.3.0
v0.3.0rc1
Version 0.3.0rc1
Installation
Install this prerelease with pip install py-horned-owl==0.3.0rc1
Overview - rust native types
Prior to version 0.3.0 axioms and other data types were expressed as S-Expressions-like lists of strings and converted to horned-owl types in rust. With the new version, local rust types (thin wrappers around horned-owl types) are exported directly, allowing a more pythonic way of interacting with the horned owl library. For example, consider the axiom
Class: Child
SubClassOf: has_parent some Human
This axiom was previously written as
[
'SubClassOf',
':Child',
[
'ObjectSomeValuesFrom',
':has_parent', 'Human'
]
]
Now it is written as
SubClassOf(
Class(IRI.parse(':Child')),
ObjectSomeValuesFrom(
ObjectProperty(IRI.parse(':has_parent')),
Class(IRI.parse(':Human'))
)
)
In contrast to the S-Expression way, we now use proper types and classes. Datatypes can be created by invoking their constructor or (in case of IRI
) their factory method. This does not only improve the readability but also allows type checkers to spot problems.
Type support
In addition to the types theirselves, version 0.3.0 adds python stubs for all classes, their fields and methods, and other functions. They can be used up by language servers and IDEs to further improve the developer experience.
Instance checking
With native rust types being exposed as python classes checking which kind of axiom or class expression is now as easy as checking the runtime type of any other python type using isinstanceof
.
Completeness
While previously the conversation between rust and python objects was implemented manually for only a subset of all types in version 0.3.0 the conversion logic is generated by macros for each datatype. Hence, all datatypes occuring in an ontology are now accessible and manipulatable from python.
Performance
A quick comparison of performance shows major improvements in interacting with axioms: For this test, the chebi_core
ontology was loaded (three times and then averaged). Then, the number of axioms was counted by iteration over all axioms in the ontology. Lastly 100.000 axioms were added to an empty ontology. Additionally, the performance of horned-owl was recorded as a baseline. Below are the performance results.
Task | 0.2.2 | 0.3.0 | horned-owl |
---|---|---|---|
Loading chebi | 26.2704s | 27.5580s | 9.9989s |
Iterating axioms | 2.7132s | 1.1928s | 3.6232 |
Adding 100.000 axioms | 4.3871s | 0.6688s | 0.04929ms |
It is unclear, why iterating all axioms is slower in native horned-owl.
Alternative approache using JSON or other serializations
Using other serializations like serde(-json) would require creating similar wrappers as now with pyo3. Furthermore, to add the same level of type support, python classes and functions would have to be created or generated to serialize and deserialize on the python side.
Examples
import pyhornedowl
from pyhornedowl.model import *
filename = "/path/to/ontology.owl"
onto = pyhornedowl.open_ontology(filename) # open and load an ontology
classes = onto.get_classes() # get all defined classes
axioms = onto.get_axioms() # get all axioms
axiom = SubClassOf(Class(onto.iri("http://example.com/A")), Class(onto.iri('http://example.com/B'))) # define a new axiom
onto.add_axiom(axiom) # add axiom to ontology
subclassaxioms = [a for a in axioms if isinstance(a.axiom, SubClassOf)] # get all SubClassOf axioms
Full Changelog: v0.2.2...v0.3.0rc.1
v0.2.2
v0.2.1
What's Changed
- Added ParserConfiguration to open function by @Eugenio2192 in #1
- Add build scripts by @Eugenio2192 in #3
- Add more py axioms by @Eugenio2192 in #5
- Add version and ontology IRI by @Eugenio2192 in #7
- Patch actions by @Eugenio2192 in #4
New Contributors
- @Eugenio2192 made their first contribution in #1
Full Changelog: https://github.com/jannahastings/py-horned-owl/commits/v0.2.1