OWL¶
Example Output¶
Overview¶
Web Ontology Language OWL is a modeling language used to author ontologies.
OWL is used for building ontologies, whereas LinkML is a schema language. Nevertheless, it can be useful to render Schemas as OWL (and in fact many semantic web schemas such as PROV have an OWL or RDFS rendering)
See also
The linkml-owl maps between LinkML data and OWL
Note
The OWL is rendered as RDF/turtle. We recommend the suffix
.owl.ttl to distinguish from the direct RDF mapping
Mapping¶
Each LinkML class maps to an OWL class
Each LinkML slot maps to an OWL property
if the range of the slot is class, then an ObjectProperty is used
otherwise DataProperty is used
Exception to the above: if
type_objectsis set then ObjectProperties are always used; instead of having ranges of type be mapped to literals, these map to class-shadows of literals, that have a data propertyvalue. This can be useful in some scenarios - for example, if you want to use the same property and allow either literals or objects as values.
OWL restrictions are used for cardinality and range constraints
only(universal restrictions) is used for rangesIf a slot is not multivalued then
max 1cardinality restrictions are usedrequired non-multivalued slots have an
exactly 1cardinality restrictionrequired slots have a
min 1cardinality restrictionnon-required slots have a
min 0cardinality restriction. Note that formally this is tautological and not necessary. However, adding this axiom helps make the intention explicit.it should be understood that OWL follows the Open World Assumption, thus OWL reasoners enforce a weaker model
By default both
is_aandmixinsare mapped tordfs:subClassOfUse
--mixins-as-expressionsto treat mixins as existential axioms
Each LinkML element is rendered as an instance of the relevant metamodel class
This means punning is used
Set
--no-metaclassesif you do not want this behaviorSet
--add-root-classesto add a root class for each metamodel class
Note
The current default settings for metaclasses and type-objects may change in the future
Enums and PermissibleValues¶
Enums and PermissibleValues provide flexible OWL representation options. By default, permissible values
are treated as classes and an enum has a definition added using an OWL UnionOf construct.
CLI Options for Controlling Enum/PV Generation¶
--default-permissible-value-type- Sets the default OWL type for permissible valuesowl:Class(default) - PVs become OWL classes, enum usesowl:unionOfowl:NamedIndividual- PVs become named individuals, enum usesowl:oneOfrdfs:Literal- PVs become RDF literals, enum usesowl:oneOf
--enum-iri-separator- Changes the separator character in enum IRIs (default:#)
Example CLI usage:
# Generate enum PVs as named individuals
gen-owl --default-permissible-value-type owl:NamedIndividual schema.yaml
# Generate enum PVs as literals
gen-owl --default-permissible-value-type rdfs:Literal schema.yaml
Schema Annotations for Fine-Grained Control¶
You can control enum and permissible value representation directly in your schema using implements annotations.
Enum-level control - Apply to all permissible values in an enum:
enums:
HomePlanetType:
implements:
- owl:NamedIndividual
description: The type of home planet
permissible_values:
Earth:
description: Third planet from the sun
Venus:
description: Second planet from the sun
Per-permissible-value control - Override specific permissible values:
enums:
MixedRepresentationType:
description: Enum with mixed PV representations
permissible_values:
concept_term:
description: A concept represented as a class
implements:
- owl:Class
instance_value:
description: A specific instance
implements:
- owl:NamedIndividual
literal_value:
description: A literal value
implements:
- rdfs:Literal
Using URIs vs. text for permissible values:
enums:
StatusEnum:
permissible_values:
active:
meaning: ex:ActiveStatus # Will use URI for OWL representation
description: Currently active
inactive:
description: Not active # Will use text-based representation
OWL Output Patterns¶
The choice of permissible value type affects the generated OWL structure:
owl:Class (default):
:StatusEnum a owl:Class ;
owl:unionOf ( :active :inactive ) .
:active a owl:Class .
:inactive a owl:Class .
owl:NamedIndividual:
:StatusEnum a owl:Class ;
owl:oneOf ( :active :inactive ) .
:active a owl:NamedIndividual .
:inactive a owl:NamedIndividual .
rdfs:Literal:
:StatusEnum a owl:Class ;
owl:oneOf ( "active" "inactive" ) .
Mixed Types in One Enum¶
When permissible values in the same enum have different implements annotations,
the behavior depends on the URI/meaning configuration:
All PVs have URIs: Mixed types are supported
Some PVs lack URIs: The enum may skip certain representation patterns that would be inconsistent
No PVs have URIs: All PVs use the same default type
Advanced Usage¶
Using with different URI patterns:
enums:
ConceptEnum:
permissible_values:
term_a:
meaning: MONDO:0001234
implements: [owl:Class]
term_b:
meaning: http://example.org/TermB
implements: [owl:NamedIndividual]
Tips¶
If you wish to produce an OWL file that is primarily for browsing or release on an ontology portal
such as the Ontology Lookup Service (OLS) or OntoPortal/BioPortal, then consider using the
--add-root-classes option to make the ontology more navigable.
If gen-owl is run on PersonInfo without this option it results in a flat structure
that is faithful and isomorphic to the existing schema:
* GenderType
* FamilialRelationshipType
* CHILD_OF
* PARENT_OF
* ...
* Relationship
* FamilialRelationship
* Event
* EmploymentEvent
* MedicalEvent
* NamedThing
* Concept
* HasAliases
Running with the option:
* EnumDefinition
* GenderType
* FamilialRelationshipType
* ClassDefinition
* Relationship
* FamilialRelationship
* Event
* EmploymentEvent
* MedicalEvent
* NamedThing
* Concept
* HasAliases
* PermissibleValue
* CHILD_OF
* ...
If your schema is heavy on mixins, the resulting polyhierarchy can be hard to navigate. In this case,
using --mixins-as-expressions will restrict the main subClassOf backbone to be purely is_a
relationships. Mixin relationships will be modeled using existential restrictions (some values from).
OWL General Class Inclusion (GCI) axioms will be used to preserve semantics.
For example, on PersonInfo the default conversion yields:
Class: Person
SubClassOf: NamedThing, HasAlias, ...
Class: HasAlias
SubClassOf: aliases only xsd:string, ...
...
Using --mixins-as-expressions gives:
Class: Person
SubClassOf: NamedThing, mixins some HasAlias, ...
Class: HasAlias
GCIs:
(mixins some HasAlias) SubClassOf: aliases only xsd:string, ...
...
Semantics of mapping from LinkML¶
Generated OWL should be a faithful open-world rendering of the LinkML schema. This means that it may not be complete for the purposes of data validation. If a slot is not required, then an OWL reasoner will infer the presence of a slot value, even if not explicitly stated. However, it does not treat this as an error.
Nevertheless, it can be informative to translate schemas with rich logical information to OWL, combine these with data converted to RDF, and then perform reasoning. If you use an ontology development environment like Protege, this can be an intuitive way of debugging errors with your schema.
Note that currently only a subset of LinkML rules can be expressed as OWL. In future, we may add support to generate auxhiliary SWRL files including rules.
Pitfalls¶
Many OWL tools such as those based on the OWL API are intended to consume a [profile](https://www.w3.org/TR/owl2-profiles/) of OWL called OWL-DL. It’s relatively easy to create LinkML that can’t be directly expressed in OWL-DL, and the resulting RDF triples are said to be [OWL Full](https://www.w3.org/TR/owl2-overview/#Semantics).
For example, if you have slots in your schema that have an Any range, then there is no direct translation of that slot to an OWL-DL property, since each property needs to explicitly commit to being a DatatypeProperty or ObjectProperty in OWL-DL.
Other examples¶
Biolink : translation of Biolink schema to OWL
Docs¶
Command Line¶
gen-owl¶
Generate an OWL representation of a LinkML model
Generate OWL using default parameters:
gen-owl my_schema.yaml
Note that in previous versions of this generator, the default was to use type objects and to include metaclasses. To restore this behavior:
gen-owl –metaclasses –type-objects my_schema.yaml
For more info, see: https://linkml.io/linkml/generators/owl
gen-owl [OPTIONS] YAMLFILE
Options
- -o, --output <output>¶
Output file name
- --metadata-profile <metadata_profile>¶
What kind of metadata profile to use for annotations on generated OWL objects
- Default:
'linkml'- Options:
linkml | rdfs | ols
- --type-objects, --no-type-objects¶
If true, will model linkml types as objects, not literals
- Default:
False
- --metaclasses, --no-metaclasses¶
If true, include linkml metamodel classes as metaclasses. Note this introduces punning in OWL-DL
- Default:
False
- --add-root-classes, --no-add-root-classes¶
If true, include linkml metamodel classes as superclasses.
- Default:
False
- --add-ols-annotations, --no-add-ols-annotations¶
If true, auto-include annotations from https://www.ebi.ac.uk/ols/docs/installation-guide
- Default:
True
- --ontology-uri-suffix <ontology_uri_suffix>¶
Suffix to append to schema id to generate OWL Ontology IRI
- Default:
'.owl.ttl'
- --assert-equivalent-classes, --no-assert-equivalent-classes¶
If true, add owl:equivalentClass between a class and a class_uri
- Default:
False
- --mixins-as-expressions, --no-mixins-as-expressions¶
If true, then mixins are represented as existential expressions
- Default:
False
- --use-native-uris, --no-use-native-uris¶
Use model URIs rather than class/slot URIs
- Default:
True
- --default-permissible-value-type <default_permissible_value_type>¶
Default OWL type for permissible values
- Default:
'http://www.w3.org/2002/07/owl#Class'
- --enum-iri-separator <enum_iri_separator>¶
IRI separator for enums.
- Default:
'#'
- -V, --version¶
Show the version and exit.
- -f, --format <format>¶
Output format
- Default:
'owl'- Options:
owl | ttl | json-ld | xml | n3 | turtle | ttl | ntriples | nt | nt11 | nquads | trix | trig | hext | patch
- --metadata, --no-metadata¶
Include metadata in output
- Default:
True
- --useuris, --metauris¶
Use class and slot URIs over model uris
- Default:
True
- -im, --importmap <importmap>¶
Import mapping file
- --log_level <log_level>¶
Logging level
- Default:
'WARNING'- Options:
CRITICAL | ERROR | WARNING | INFO | DEBUG
- -v, --verbose¶
Verbosity. Takes precedence over –log_level.
- --mergeimports, --no-mergeimports¶
Merge imports into source file (default=mergeimports)
- --stacktrace, --no-stacktrace¶
Print a stack trace when an error occurs
- Default:
False
Arguments
- YAMLFILE¶
Required argument
Code¶
- class linkml.generators.owlgen.OwlSchemaGenerator(schema: str | ~typing.TextIO | ~linkml_runtime.linkml_model.meta.SchemaDefinition | ~linkml.utils.generator.Generator | ~pathlib.Path, schemaview: ~linkml_runtime.utils.schemaview.SchemaView | None = None, format: str | None = None, metadata: bool = True, useuris: bool | None = None, log_level: int | None = 30, mergeimports: bool | None = True, source_file_date: str | None = None, source_file_size: int | None = None, logger: ~logging.Logger | None = None, verbose: bool | None = None, output: str | None = None, namespaces: ~linkml_runtime.utils.namespaces.Namespaces | None = None, directory_output: bool = False, base_dir: str = None, metamodel_name_map: dict[str, str] = None, importmap: str | ~collections.abc.Mapping[str, str] | None = None, emit_prefixes: set[str] = <factory>, metamodel: ~linkml.utils.schemaloader.SchemaLoader = None, stacktrace: bool = False, include: str | ~pathlib.Path | ~linkml_runtime.linkml_model.meta.SchemaDefinition | None = None, ontology_uri_suffix: str = None, metadata_profile: ~linkml.generators.owlgen.MetadataProfile = None, metadata_profiles: list[~linkml.generators.owlgen.MetadataProfile] = <factory>, metaclasses: bool = True, add_root_classes: bool = False, add_ols_annotations: bool = True, graph: ~rdflib.graph.Graph | None = None, top_value_uri: ~rdflib.term.URIRef | None = None, type_objects: bool = True, assert_equivalent_classes: bool = False, use_native_uris: bool = True, mixins_as_expressions: bool = None, default_permissible_value_type: str | ~rdflib.term.URIRef = <factory>, slot_is_literal_map: ~collections.abc.Mapping[str, set[bool]] = <factory>, node_owltypes: ~collections.abc.Mapping[~rdflib.term.BNode | ~rdflib.term.URIRef, set[~rdflib.term.URIRef]] = <factory>, simplify: bool = True, use_swrl: bool = False, target_profile: ~linkml.generators.owlgen.OWLProfile = <factory>, metamodel_schemaview: ~linkml_runtime.utils.schemaview.SchemaView = <factory>, enum_iri_separator: str = '#')[source]¶
Generates a schema-oriented OWL representation of a LinkML model
.
LinkML ClassDefinitions are translated to OWL Classes
LinkML SlotDefinitions are translated to OWL Properties
LinkML Enumerations are translated to OWL Classes
LinkML TypeDefinitions are translated to OWL Datatypes
The translation aims to be as faithful as possible. But note that OWL is open-world, whereas LinkML is closed-world