gist-to-LinkML transform
services/gist-to-linkmlNobody has checked this yet
still a draft
Written 2026-10-28 by ktl-librarian (automation).
The full record
- Checks
- none recorded
- Sources
- Depends on
- Pointed to by
- gist namespace policy (references)
- Regenerate the schema and its artefacts (references)
- Graph
- Open this concept in the knowledge graph
- IRI
https://w3id.org/lmodel/gist/knowledge/services/gist-to-linkml- Licence
- CC BY 4.0
- Files
- MarkdownJSON-LDSource on GitHubHistory on GitHub
gist-to-LinkML transform
Section titled “gist-to-LinkML transform”The transform reads the upstream Turtle modules with rdflib and writes one LinkML schema per module into src/gist/schema/: gist_core.yaml (enriched by the RdfsAnnotations and SubClassAssertions modules), gist_media_types.yaml, gist_prefix_declarations.yaml, gist_rdfs_annotations.yaml and gist_sub_class_assertions.yaml, plus the aggregator gist.yaml. The result is the gist LinkML schema. Run it as uv run python scripts/gist_to_linkml.py [TTL_FILE ...] [-d OUTPUT_DIR] [--rename OLD=NEW ...], which just gen-linkml runs.
Its stated goal is full coverage:
- every
owl:Classbecomes a class; - every object, datatype and gist annotation property becomes a slot, and an annotation property’s slot says so with
implements: owl:AnnotationProperty; - the slot of an object or datatype property belongs to each class its
rdfs:domainnames, alone or in a union, and to their subclasses; - the slot of a property gist declares without a domain belongs to the
GistThingmixin, which every class includes, because OWL lets that property describe any individual; gist:domainIncludesandrangeIncludesbecome slot annotations only, never a domain or a range;owl:FunctionalPropertybecomesmultivalued: false;- an object property that gist leaves unranged takes the range of its nearest ranged superproperty, or else
Any, a class whoseclass_uriislinkml:Any; - a union range becomes
any_of, withAnyas its range; - each XSD or OWL datatype becomes the
linkml:typestype with that datatype’s IRI, or, where there is none, a type ofgist_corewith that IRI, such asxsd_int; - an element’s
skos:prefLabel, or else itsrdfs:label, becomes itstitle, and its other labels become aliases; - a term gist marks
owl:deprecatedgets a reason indeprecatedand anowl:deprecated: trueannotation, which the generated OWL contains; - named individuals become enum permissible values;
- SHACL prefix declarations become the
PrefixDeclarationInstanceenum; - SKOS and RDFS annotations are kept on classes, slots, individuals and each module’s ontology header, without their Windows line ends and the tab indent their lines share;
- OWL axioms with no LinkML equivalent, such as restrictions, equivalent classes and union domains, are kept as notes.
The transform stops with an error at a domain whose slot no set of classes carries faithfully:
- two domains, which OWL reads as their intersection;
- an anonymous class other than a union;
- a class that gist does not declare.
gist 14.1.0 has none of these.
The transform keeps each term’s gist IRI: class_uri and slot_uri are gist: CURIEs in Semantic Arts’ namespace. Only what it adds gets an IRI in lmodel’s gist_linkml: namespace: the GistThing mixin, the types for the datatypes linkml:types lacks, the enums and the subsets (gist namespace policy). Its output is deterministic: it relabels blank nodes canonically and reads the graph in sorted order, so a rerun reproduces the committed schema byte for byte. tests/test_owl_to_linkml.py holds 231 unit tests for it.
--rename OLD=NEW, which can be repeated, gives a gist class or slot another LinkML name. The element keeps its IRI, and takes its old name as an alias unless that is already its title. Every reference to the element is rewritten. A schema that imports gist beside another vocabulary defining the same name needs this option, because LinkML keeps only the last import’s definition of a name.