Skip to content

Commit f2782d8

Browse files
committedOct 24, 2024·
First pass at revised version of COB
This revision is based on the results of the September 2024 COB workshop. Changes have not yet been vetted.
1 parent 0787b2f commit f2782d8

15 files changed

+2198
-9938
lines changed
 

‎cob-base.owl

+200-2,920
Large diffs are not rendered by default.

‎cob-full.owl

-1,456
This file was deleted.

‎cob-root.owl

+1,254
Large diffs are not rendered by default.

‎cob.owl

+483-763
Large diffs are not rendered by default.

‎docs/odk-workflows/RepositoryFileStructure.md

-7
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ These are the current imports in COB
1616

1717
| Import | URL | Type |
1818
| ------ | --- | ---- |
19-
| ro | http://purl.obolibrary.org/obo/ro.owl | custom |
20-
| omo | http://purl.obolibrary.org/obo/omo.owl | mirror |
2119

2220
## Components
2321
Components, in contrast to imports, are considered full members of the ontology. This means that any axiom in a component is also included in the ontology base - which means it is considered _native_ to the ontology. While this sounds complicated, consider this: conceptually, no component should be part of more than one ontology. If that seems to be the case, we are most likely talking about an import. Components are often not needed for ontologies, but there are some use cases:
@@ -26,9 +24,4 @@ Components, in contrast to imports, are considered full members of the ontology.
2624
2. A part of the ontology is managed in ROBOT templates
2725
3. The expressivity of the component is higher than the format of the edit file. For example, people still choose to manage their ontology in OBO format (they should not) missing out on a lot of owl features. They may choose to manage logic that is beyond OBO in a specific OWL component.
2826

29-
These are the components in COB
3027

31-
| Filename | URL |
32-
| -------- | --- |
33-
| cob-annotations.owl | None |
34-
| cob-to-external.owl | None |

‎src/ontology/Makefile

+4-72
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# 6. [Run everything (COB products and release pipeline)](all)
2020

2121
# Fingerprint of the configuration file when this Makefile was last generated
22-
CONFIG_HASH= 5daef41d99e802417bd9ad0f378f72168e2d30f0488f5b2423330cbc561ec834
22+
CONFIG_HASH= 0cb0824fc712dd1bbe3e3067c8a9d6d4212a769da65f9ec96e0020e31e2cafb9
2323

2424

2525
# ----------------------------------------
@@ -62,13 +62,13 @@ OBODATE ?= $(shell date +'%d:%m:%Y %H:%M')
6262
VERSION= $(TODAY)
6363
ANNOTATE_ONTOLOGY_VERSION = annotate -V $(ONTBASE)/releases/$(VERSION)/$@ --annotation owl:versionInfo $(VERSION)
6464
ANNOTATE_CONVERT_FILE = annotate --ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) convert -f ofn --output $@.tmp.owl && mv $@.tmp.owl $@
65-
OTHER_SRC = $(COMPONENTSDIR)/cob-annotations.owl $(COMPONENTSDIR)/cob-to-external.owl
65+
OTHER_SRC =
6666
ONTOLOGYTERMS = $(TMPDIR)/ontologyterms.txt
6767
EDIT_PREPROCESSED = $(TMPDIR)/$(ONT)-preprocess.owl
6868

6969
FORMATS = $(sort owl owl)
7070
FORMATS_INCL_TSV = $(sort $(FORMATS) tsv)
71-
RELEASE_ARTEFACTS = $(sort $(ONT)-base $(ONT)-full cob-base-reasoned cob-examples-reasoned cob-native )
71+
RELEASE_ARTEFACTS = $(sort $(ONT)-base $(ONT)-root )
7272

7373
ifeq ($(ODK_DEBUG),yes)
7474
ODK_DEBUG_FILE = debug.log
@@ -168,7 +168,7 @@ all_main: $(MAIN_FILES)
168168
# ----------------------------------------
169169

170170

171-
IMPORTS = ro omo
171+
IMPORTS =
172172

173173
IMPORT_ROOTS = $(patsubst %, $(IMPORTDIR)/%_import, $(IMPORTS))
174174
IMPORT_OWL_FILES = $(foreach n,$(IMPORT_ROOTS), $(n).owl)
@@ -375,16 +375,6 @@ $(IMPORTDIR)/%_import.owl: $(MIRRORDIR)/%.owl $(IMPORTDIR)/%_terms_combined.txt
375375

376376
.PRECIOUS: $(IMPORTDIR)/%_import.owl
377377

378-
## Module for ontology: ro
379-
380-
$(IMPORTDIR)/ro_import.owl: $(MIRRORDIR)/ro.owl
381-
echo "ERROR: You have configured your default module type to be custom; this behavior needs to be overwritten in cob.Makefile!" && false
382-
## Module for ontology: omo
383-
384-
$(IMPORTDIR)/omo_import.owl: $(MIRRORDIR)/omo.owl $(IMPORTDIR)/omo_terms_combined.txt
385-
if [ $(IMP) = true ]; then $(ROBOT) merge -i $< query --update ../sparql/preprocess-module.ru --update ../sparql/inject-subset-declaration.ru --update ../sparql/inject-synonymtype-declaration.ru --update ../sparql/postprocess-module.ru \
386-
$(ANNOTATE_CONVERT_FILE); fi
387-
388378

389379
.PHONY: refresh-imports
390380
refresh-imports:
@@ -406,39 +396,6 @@ refresh-%:
406396
no-mirror-refresh-%:
407397
$(MAKE) IMP=true IMP_LARGE=true MIR=false PAT=false $(IMPORTDIR)/$*_import.owl -B
408398

409-
410-
# ----------------------------------------
411-
# Components
412-
# ----------------------------------------
413-
# Some ontologies contain external and internal components. A component is included in the ontology in its entirety.
414-
415-
COMP=true # Global parameter to bypass component generation
416-
417-
.PHONY: all_components
418-
all_components: $(OTHER_SRC)
419-
420-
.PHONY: recreate-components
421-
recreate-components:
422-
$(MAKE) COMP=true IMP=false MIR=true PAT=true IMP_LARGE=false all_components -B
423-
424-
.PHONY: no-mirror-recreate-components
425-
no-mirror-recreate-components:
426-
$(MAKE) COMP=true IMP=false MIR=false PAT=true IMP_LARGE=false all_components -B
427-
428-
.PHONY: recreate-%
429-
recreate-%:
430-
$(MAKE) COMP=true IMP=false IMP_LARGE=false MIR=true PAT=true $(COMPONENTSDIR)/$*.owl -B
431-
432-
.PHONY: no-mirror-recreate-%
433-
no-mirror-recreate-%:
434-
$(MAKE) COMP=true IMP=false IMP_LARGE=false MIR=false PAT=true $(COMPONENTSDIR)/$*.owl -B
435-
436-
$(COMPONENTSDIR)/%.owl: | $(COMPONENTSDIR)
437-
test -f $@ || touch $@
438-
.PRECIOUS: $(COMPONENTSDIR)/%.owl
439-
440-
441-
442399
# ----------------------------------------
443400
# Mirroring upstream ontologies
444401
# ----------------------------------------
@@ -450,22 +407,6 @@ IMP_LARGE=true # Global parameter to bypass handling of large imports
450407
ifeq ($(strip $(MIR)),true)
451408

452409

453-
## ONTOLOGY: ro
454-
.PHONY: mirror-ro
455-
.PRECIOUS: $(MIRRORDIR)/ro.owl
456-
mirror-ro: | $(TMPDIR)
457-
curl -L $(OBOBASE)/ro.owl --create-dirs -o $(TMPDIR)/ro-download.owl --retry 4 --max-time 200 && \
458-
$(ROBOT) convert -i $(TMPDIR)/ro-download.owl -o $(TMPDIR)/$@.owl
459-
460-
461-
## ONTOLOGY: omo
462-
.PHONY: mirror-omo
463-
.PRECIOUS: $(MIRRORDIR)/omo.owl
464-
mirror-omo: | $(TMPDIR)
465-
curl -L $(OBOBASE)/omo.owl --create-dirs -o $(TMPDIR)/omo-download.owl --retry 4 --max-time 200 && \
466-
$(ROBOT) convert -i $(TMPDIR)/omo-download.owl -o $(TMPDIR)/$@.owl
467-
468-
469410
$(MIRRORDIR)/%.owl: mirror-% | $(MIRRORDIR)
470411
if [ -f $(TMPDIR)/mirror-$*.owl ]; then if cmp -s $(TMPDIR)/mirror-$*.owl $@ ; then echo "Mirror identical, ignoring."; else echo "Mirrors different, updating." &&\
471412
cp $(TMPDIR)/mirror-$*.owl $@; fi; fi
@@ -549,15 +490,6 @@ $(ONT)-full.owl: $(EDIT_PREPROCESSED) $(OTHER_SRC) $(IMPORT_FILES)
549490
relax \
550491
reduce -r ELK \
551492
$(SHARED_ROBOT_COMMANDS) annotate --ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) --output $@.tmp.owl && mv $@.tmp.owl $@
552-
553-
cob-base-reasoned.owl:
554-
echo "ERROR: You have configured a custom release artefact ($@); this release artefact needs to be define in cob.Makefile!" && false
555-
556-
cob-examples-reasoned.owl:
557-
echo "ERROR: You have configured a custom release artefact ($@); this release artefact needs to be define in cob.Makefile!" && false
558-
559-
cob-native.owl:
560-
echo "ERROR: You have configured a custom release artefact ($@); this release artefact needs to be define in cob.Makefile!" && false
561493
# ----------------------------------------
562494
# Debugging Tools
563495
# ----------------------------------------

‎src/ontology/cob-edit.owl

-1,368
This file was deleted.

‎src/ontology/cob-edit.tsv

+133
Large diffs are not rendered by default.

‎src/ontology/cob-odk.yaml

+2-15
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,14 @@ workflows:
1010
- docs
1111
release_artefacts:
1212
- base
13-
- full
14-
- custom-cob-base-reasoned
15-
- custom-cob-examples-reasoned
16-
- custom-cob-native
13+
- root
1714
import_group:
1815
module_type: filter
1916
annotation_properties:
2017
- rdfs:label
2118
- IAO:0000115
2219
- IAO:0000116
2320
- IAO:0000111
24-
products:
25-
- id: ro
26-
module_type: custom
27-
slme_individuals: exclude
28-
- id: omo
29-
module_type: mirror
30-
components:
31-
products:
32-
- filename: cob-annotations.owl
33-
- filename: cob-to-external.owl
3421
robot_java_args: '-Xmx8G'
3522
custom_makefile_header: |
3623
### Workflow
@@ -47,4 +34,4 @@ custom_makefile_header: |
4734
# 6. [Run everything (COB products and release pipeline)](all)
4835
create_obo_metadata: FALSE
4936
documentation:
50-
documentation_system: mkdocs
37+
documentation_system: mkdocs

‎src/ontology/cob.Makefile

+30-79
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,11 @@ SHELL := bash
1010
.SUFFIXES:
1111
.SECONDARY:
1212

13-
COB_TO_EXTERNAL = $(COMPONENTSDIR)/cob-to-external.owl
14-
COB_ANNOTATIONS = $(COMPONENTSDIR)/cob-annotations.owl
15-
COB_EXAMPLES = $(COMPONENTSDIR)/cob-examples.owl
16-
1713
.PHONY: prepare_release
18-
prepare_release: $(ASSETS) $(PATTERN_RELEASE_FILES) cob.tsv
19-
rsync -R $(RELEASE_ASSETS) cob.tsv $(RELEASEDIR) &&\
20-
rm -f $(CLEANFILES) &&\
21-
rm -f cob.tsv &&\
22-
echo "Release files are now in $(RELEASEDIR) - now you should commit, push and make a release on your git hosting site such as GitHub or GitLab"
14+
prepare_release: $(ASSETS) $(PATTERN_RELEASE_FILES)
15+
rsync -R $(RELEASE_ASSETS) $(RELEASEDIR) &&\
16+
rm -f $(CLEANFILES) &&\
17+
echo "Release files are now in $(RELEASEDIR) - now you should commit, push and make a release on your git hosting site such as GitHub or GitLab"
2318

2419
.PHONY: prepare_cob_products
2520
prepare_cob_products: test
@@ -36,88 +31,44 @@ products/:
3631
$(TMPDIR)/robot.jar: | $(TMPDIR)
3732
if [ $(ROBOT_DOWNLOAD) = true ]; then curl -L -o $@ https://build.obolibrary.io/job/ontodev/job/robot/job/master/lastSuccessfulBuild/artifact/bin/robot.jar; fi
3833

34+
3935
########################################
40-
# -- MAIN RELEASE PRODUCTS --
36+
# -- TEMPLATES --
4137
########################################
4238

43-
# build main release product
44-
REWIRE_PRECEDENCE = PR CHEBI
45-
cob.ttl: components/cob-to-external.tsv cob-native.owl
46-
sssom rewire -I xml -m $< $(patsubst %,--precedence %,$(REWIRE_PRECEDENCE)) cob-native.owl -o $@
39+
$(TMPDIR)/cob-%.tsv: $(SCRIPTSDIR)/split-cob-edit.py cob-edit.tsv
40+
$^ $(TMPDIR)
4741

48-
cob.owl: cob.ttl
49-
robot merge --include-annotations true -i $< -i ontology-metadata.owl \
50-
annotate --ontology-iri $(URIBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) \
51-
--output $@.tmp.owl && mv $@.tmp.owl $@
52-
.PRECIOUS: cob.owl
5342

54-
cob-native.owl: $(SRC)
55-
$(ROBOT) remove --input $< --select imports --trim false \
56-
reason -r HERMIT \
57-
annotate --ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) \
58-
--output $@.tmp.owl && mv $@.tmp.owl $@
43+
########################################
44+
# -- MAIN RELEASE PRODUCTS --
45+
########################################
5946

60-
# base file is main cob plus linking axioms
61-
#cob-base.owl: cob.owl $(COB_TO_EXTERNAL)
62-
# $(ROBOT) merge $(patsubst %, -i %, $^) -o $@
47+
$(ONT)-edit.owl: $(TMPDIR)/cob-root.tsv
48+
$(ROBOT) template --template $< \
49+
reason -r HERMIT \
50+
annotate --ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) \
51+
--output $@.tmp.owl && mv $@.tmp.owl $@
6352

64-
$(ONT)-base.owl: $(EDIT_PREPROCESSED) $(OTHER_SRC)
65-
$(ROBOT_RELEASE_IMPORT_MODE_BASE) \
66-
$(SHARED_ROBOT_COMMANDS) \
53+
# COB "Full"
54+
$(ONT).owl: $(TMPDIR)/cob-full.tsv
55+
$(ROBOT) template --template $< \
56+
reason -r HERMIT \
57+
annotate --ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) \
58+
--output $@.tmp.owl && mv $@.tmp.owl $@
59+
60+
$(ONT)-base.owl: $(ONT).owl $(TMPDIR)/cob-base.tsv
61+
$(ROBOT) template --input $< --template $(word 2,$^) \
6762
annotate --link-annotation http://purl.org/dc/elements/1.1/type http://purl.obolibrary.org/obo/IAO_8000001 \
6863
--ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) \
6964
--output $@.tmp.owl && mv $@.tmp.owl $@
7065

71-
cob-base-reasoned.owl: cob-base.owl
72-
$(ROBOT) remove --input $< --select imports --trim false \
73-
reason -r HERMIT \
74-
annotate --ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) \
75-
--output $@.tmp.owl && mv $@.tmp.owl $@
76-
77-
cob-examples-reasoned.owl: cob-base.owl $(COB_EXAMPLES)
78-
$(ROBOT) remove --input $< --select imports --trim false \
79-
merge $(patsubst %, -i %, $^) \
80-
reason -r HERMIT \
81-
annotate --ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) \
82-
--output $@.tmp.owl && mv $@.tmp.owl $@
83-
84-
# TSV export (may depend on dev version of robot export)
85-
cob.tsv: cob.owl
86-
$(ROBOT) export -i $< -c "ID|ID [LABEL]|definition|subClassOf [ID NAMED]|subClassOf [LABEL NAMED]|subClassOf [ID ANON]|subClassOf [LABEL ANON]" -e $@
87-
# $(ROBOT) export -i $< --entity-select NAMED -c "ID|ID [LABEL]|definition|subClassOf [ID]|subClassOf [LABEL]|subClassOf [ID ANON]|subClassOf [LABEL ANON]" -e $@
88-
89-
# -- BRIDGING AXIOMS TO OBO ROOTS --
90-
#
91-
# the source file is cob-to-external.tsv
92-
#
93-
# OWL is generated from this
94-
#
95-
96-
$(TMPDIR)/cob-to-external.sssom.owl: $(COMPONENTSDIR)/cob-to-external.tsv | $(TMPDIR)
97-
sssom convert $< --output-format owl -o $@
98-
99-
$(COB_TO_EXTERNAL): $(TMPDIR)/cob-to-external.sssom.owl
100-
$(ROBOT) merge -i $< \
66+
$(ONT)-root.owl: $(TMPDIR)/cob-root.tsv
67+
$(ROBOT) template --template $< \
68+
reason -r HERMIT \
10169
annotate --ontology-iri $(ONTBASE)/$@ $(ANNOTATE_ONTOLOGY_VERSION) \
102-
convert -f owl -o $@
103-
104-
$(TMPDIR)/cob-annotations.ttl: $(COB_TO_EXTERNAL) $(SPARQLDIR)/external-links.rq | $(TMPDIR)
105-
$(ROBOT) query --input $< --query $(word 2,$^) $@
106-
107-
$(COB_ANNOTATIONS): $(TMPDIR)/cob-annotations.ttl
108-
$(ROBOT) annotate --input $< \
109-
--ontology-iri "http://purl.obolibrary.org/obo/cob/$@" \
110-
--annotation owl:versionInfo $(TODAY) \
111-
--output $@
112-
113-
# This is the custom import: removing all COB related axioms from RO, but otherwise pulling in logical dependencies.
70+
--output $@.tmp.owl && mv $@.tmp.owl $@
11471

115-
$(IMPORTDIR)/ro_import.owl: $(MIRRORDIR)/ro.owl $(IMPORTDIR)/ro_terms_combined.txt
116-
if [ $(IMP) = true ]; then $(ROBOT) query -i $< --update ../sparql/preprocess-module.ru \
117-
extract -T $(IMPORTDIR)/ro_terms_combined.txt --copy-ontology-annotations true --force true --individuals exclude --method BOT \
118-
remove --base-iri http://purl.obolibrary.org/obo/COB_ --axioms internal --preserve-structure false --trim false \
119-
query --update ../sparql/inject-subset-declaration.ru --update ../sparql/inject-synonymtype-declaration.ru --update ../sparql/postprocess-module.ru \
120-
$(ANNOTATE_CONVERT_FILE); fi
12172

12273
########################################
12374
# -- TESTING --
@@ -151,7 +102,7 @@ cob_test: main_test itest
151102
# main test: should be run via CI on every PR
152103
# this tests COB's internal consistency
153104
.PHONY: main_test
154-
main_test: $(REPORTDIR)/$(SRC)-obo-report.tsv cob.owl cob-base-reasoned.owl cob-examples-reasoned.owl
105+
main_test: $(REPORTDIR)/$(SRC)-obo-report.tsv $(RELEASEDIR)/cob-root.owl
155106
test: main_test
156107

157108
# integration tests: for now, run these on commmand line

‎src/ontology/components/cob-annotations.owl

-226
This file was deleted.

‎src/ontology/components/cob-examples.owl

-552
This file was deleted.

‎src/ontology/components/cob-to-external.owl

-2,338
This file was deleted.

‎src/ontology/components/cob-to-external.tsv

-142
This file was deleted.

‎src/scripts/split-cob-edit.py

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Split the cob-edit.tsv file into three ROBOT templates:
4+
# cob-base.tsv cob-full.tsv cob-root.tsv
5+
6+
import argparse
7+
import csv
8+
import os
9+
import re
10+
11+
12+
def initialize_tsv(output_dir, filename, fieldnames, robot_row):
13+
'''Initialize and return a DictWriter for a ROBOT template.'''
14+
path = os.path.join(output_dir, filename)
15+
path_fh = open(path, 'w')
16+
writer = csv.DictWriter(path_fh, fieldnames, delimiter='\t', lineterminator='\n', extrasaction='ignore')
17+
writer.writeheader()
18+
writer.writerow(robot_row)
19+
return writer
20+
21+
22+
def split(input_path, output_dir):
23+
'''Split the COB term template into base, full, and root templates.'''
24+
fieldnames = None
25+
robot_row, terms, replacements = {}, {}, {}
26+
27+
with open(input_path) as f:
28+
rows = csv.DictReader(f, delimiter='\t')
29+
for row in rows:
30+
if not fieldnames:
31+
# Ignore the last three columns
32+
fieldnames = list(row.keys())[0:-3]
33+
id = row['Ontology ID'].strip()
34+
if id == '':
35+
continue
36+
if id == 'ID':
37+
robot_row = row
38+
continue
39+
40+
# Handle the Replacement columns
41+
# by collecting a dictionary of replacements.
42+
replacement_id = row['Replacement ID'].strip()
43+
replacement_label = row['Replacement Label'].strip()
44+
if replacement_label and replacement_label != '':
45+
# removed exception for non-base IDs... TBD if needed/wanted
46+
replacements[row['Label'].strip()] = {
47+
'ID': id,
48+
'Replacement Label': replacement_label,
49+
'Replacement ID': replacement_id,
50+
}
51+
# Otherwise just add this row to 'terms'.
52+
else:
53+
terms[id] = row
54+
55+
# Apply replacements to the axioms in all the logical columns
56+
axiom_cols = [
57+
'Parent Class', 'Subclass Axiom', 'Equivalent Class Axiom',
58+
'Disjoint Class', 'Parent Property', 'Domain', 'Range',
59+
'Inverse Property'
60+
]
61+
for id, row in terms.items():
62+
for repl_label, repl_dict in replacements.items():
63+
for col in axiom_cols:
64+
if col not in row:
65+
continue
66+
row[col] = re.sub(repl_label, repl_dict['Replacement Label'], row[col])
67+
68+
base_writer = initialize_tsv(output_dir, 'cob-base.tsv', fieldnames, robot_row)
69+
full_writer = initialize_tsv(output_dir, 'cob-full.tsv', fieldnames, robot_row)
70+
root_writer = initialize_tsv(output_dir, 'cob-root.tsv', fieldnames, robot_row)
71+
72+
for id, row in terms.items():
73+
module = row['COB Module'].strip()
74+
if module == 'BASE':
75+
base_writer.writerow(row)
76+
if module not in ['', 'ROOT']:
77+
full_writer.writerow(row)
78+
if module != '':
79+
root_writer.writerow(row)
80+
81+
82+
def main():
83+
parser = argparse.ArgumentParser(description='Split the main COB term template into multiple module templates')
84+
parser.add_argument('input', type=str, help='The input COB term template')
85+
parser.add_argument('outdir', type=str, help='The output directory')
86+
args = parser.parse_args()
87+
88+
split(args.input, args.outdir)
89+
90+
91+
if __name__ == '__main__':
92+
main()

0 commit comments

Comments
 (0)