Repository navigation
Proposal: a command that applies a mapping set to a LinkML schema's mapping slots #678
Description
Background
I spend a lot of time on integration challenges, contributing foundational fixes and sometimes features to LinkML. But I understand the benefit of SSOM and have been using SSSOM TSV format in various domain mapping experiments, and more recently discussing the ai-atlas-nexus mappings with that maintainer, and I mentioned sssom to someone from Apache Ossie and read a paper - but I also have my own use cases - I would like to see better foundational features in tools like LinkML and sssom so I can switch to Domain schemas properly.
Over past year, in scattered POC repositories, I built various iterations of map-ssom-to-linkml tools, but started looking for upstream owner so I could inherit the tooling. I raised linkml/linkml-project-copier#176 and proposed linkml/linkml-project-copier#177 which in particular captures my doubts about trying to sidestep sssom-py and so I decided to raise this proposal. An alternative is linkml/linkml-project-copier#186
A LinkML schema carries mappings on every class, slot, enum and permissible value, in five mapping slots, and in the parent mappings (skos:mappingRelation). Curation teams using SSSOM today copy them into those slots by hand, or write a project-local script to do it (my solution). I noticed gen-sssom in linkml goes the other way, so the two tools together would give a round trip. But the highest value is sssom-py to linkml in my opinion.
Proposal for sssom feature
A command sssom apply --target linkml that takes one or more SSSOM TSV files and the LinkML schema YAML file to edit, and writes the schema back with every mapping the files carry that the schema does not already hold. --target names the kind of thing the mapping set is applied to, an extension point:
Example rules (see linkml-project-copier#163, but sssom maintainers should specify the rules?
-
predicate chooses the slot: skos:exactMatch, owl:equivalentClass and owl:equivalentProperty go to exact_mappings;
-
skos:closeMatch, skos:broadMatch, skos:narrowMatch and skos:relatedMatch to the slot of the same name;
-
skos:mappingRelation to mappings. Any other predicate is an error, since metamodel has no slot for it.
-
A row whose predicate_modifier is Not, or whose object is sssom:NoTermFound, states the absence of a mapping and is skipped.
The subject must resolve to element of schema file being edited: by the URI it declares (class_uri and the like), by its native URI under the schema's default prefix, or by its bare name. A permissible value is addressed as #, the form gen-sssom writes. A subject that resolves to nothing, including an element only an import defines, is an error.
The object is kept as the CURIE in the file. A prefix the schema does not declare is copied from the mapping set's curie_map into the schema's prefixes; a prefix found in neither is an error.
An exact match whose object is the URI the element already declares as class_uri, slot_uri, enum_uri or meaning is already expressed and is not repeated.
The operation only adds, and it is idempotent. Removing a row from the TSV removes nothing from the schema; gen-sssom exports what the schema holds so the two can be compared.
mapping_justification, confidence and the other SSSOM columns have no counterpart in the mapping slots and stay in the files. Closing that gap is linkml/linkml#922.
A --check flag writes nothing, lists the mappings the schema lacks and exits 1 when there are any, which is what a CI gate needs. The schema is rewritten with a round-trip YAML writer so that comments and layout survive and a second run produces an identical file.
Alternatives
As mentioned, I feel the place for this is sssom-py because it makes enablement and integration of sssom mappings in downstream project much easier - curation teams can focus on mappings domain - instead of fighting integration pains and reinventing the wheel.
In Slack someone mentioned "replaying semantics over a model" (sic) - because they were regenerating the linkml models so hand crafting mappings makes no sense - this is actually a pattern I use also, rebuilding linkml model from a source and then replaying sssom mappings on-demand.
Activity