Skip to content

Commit f5dbb74

Browse files
authored
Merge pull request #36 from linkml/fix-uriref-in-tr-expression
Adding test for tr function in templates
2 parents cd19641 + 5646fd1 commit f5dbb74

File tree

4 files changed

+147
-75
lines changed

4 files changed

+147
-75
lines changed

linkml_owl/dumpers/owl_dumper.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
SubObjectPropertyOf, TransitiveObjectProperty, SymmetricObjectProperty, AsymmetricObjectProperty, \
3434
ReflexiveObjectProperty, IrreflexiveObjectProperty, Annotation, ObjectMinCardinality, ObjectHasValue, \
3535
NamedIndividual, DataSomeValuesFrom, DataHasValue, DataAllValuesFrom, AnnotationProperty, DataProperty, Datatype, \
36-
DisjointClasses
36+
DisjointClasses, DisjointUnion
3737

3838
from linkml_runtime.dumpers.dumper_root import Dumper
3939
from linkml_runtime.utils.yamlutils import YAMLRoot
@@ -194,7 +194,7 @@ def transform(self, element: YAMLRoot, schema: SchemaDefinition, is_element_an_o
194194
"""
195195
Recursively transform a LinkML element
196196
197-
Each field is introspected, and translated to an OWL axiom.
197+
Each field is introspected, and translated to an OWL axiom or expression.
198198
The field value is recursively transformed
199199
200200
:param element:
@@ -461,6 +461,7 @@ def transform(self, element: YAMLRoot, schema: SchemaDefinition, is_element_an_o
461461
for op_key, operands in eai.operand_list_index.items():
462462
_, interp, operator = op_key
463463
logging.debug(f'EntityAxiomIndex {subj}: {interp} => {operator} over {operands}')
464+
# pre-process operands
464465
if len(operands) == 0:
465466
raise ValueError(f'Too few operands: {operands} for {operator} in {subj}')
466467
if len(operands) == 1:
@@ -476,12 +477,15 @@ def transform(self, element: YAMLRoot, schema: SchemaDefinition, is_element_an_o
476477
expr = ObjectIntersectionOf(*operands)
477478
else:
478479
raise ValueError(f'Cannot handle operator: {operator}')
480+
# interpret as axiom
479481
if interp == EquivalentClasses.__name__:
480482
axiom = EquivalentClasses(subj, expr)
481483
elif interp == SubClassOf.__name__:
482484
axiom = SubClassOf(subj, expr)
483485
elif interp == DisjointClasses.__name__:
484486
axiom = DisjointClasses(subj, expr)
487+
elif interp == DisjointUnion.__name__:
488+
axiom = DisjointUnion(operands[0], operands[1:])
485489
else:
486490
raise ValueError(f'Not handled: {interp}')
487491
logging.debug(f'Adding axiom: {axiom}')
@@ -698,7 +702,10 @@ def tr(e: YAMLRoot):
698702
def _tr(x):
699703
fw = FunctionalWriter()
700704
expr = self.transform(x, schema)
701-
return expr.to_functional(fw)
705+
if isinstance(expr, URIRef):
706+
return str(expr)
707+
else:
708+
return expr.to_functional(fw)
702709
d["tr"] = _tr
703710
owl_str = jt.render(**d)
704711
axioms = self.parse_axioms_string(owl_str).ontology.axioms

tests/inputs/owl_dumper_test.yaml

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ slots:
7777
range: NamedThing
7878
multivalued: true
7979
description: named class this is subclass of
80+
subclass_of_anon:
81+
slot_uri: rdfs:subclass_of
82+
range: AnonPartOf
83+
multivalued: true
84+
inlined: true
85+
inlined_as_list: true
8086
operands:
8187
range: NamedThing
8288
multivalued: true
@@ -197,10 +203,10 @@ classes:
197203
is_a: NamedThing
198204
description: test metaclass illustrating classes with parents that are class expressions
199205
slots:
200-
- subclass_of
206+
- subclass_of_anon
201207
slot_usage:
202-
subclass_of:
203-
range: AnonPartOf
208+
subclass_of_anon:
209+
required: true
204210
annotations:
205211
owl: SubClassOf
206212
DirectEquivalent:
@@ -246,7 +252,7 @@ classes:
246252
operands:
247253
required: true
248254
annotations:
249-
owl: DisjointUnionOf
255+
owl: DisjointUnion
250256
EquivIntersection:
251257
is_a: NamedThing
252258
description: test metaclass illustrating classes defined by a simple intersection of classes
@@ -323,7 +329,7 @@ classes:
323329
annotations:
324330
owl: EquivalentClasses, IntersectionOf
325331
part_of:
326-
required: true
332+
required: false
327333
description: the part-of differentiae
328334
annotations:
329335
owl: EquivalentClasses, IntersectionOf, ObjectSomeValuesFrom
@@ -458,20 +464,22 @@ classes:
458464
range: NamedThing
459465
multivalued: false
460466
annotations:
461-
owl: SomeValuesFrom
467+
owl: SomeValuesFrom, ObjectProperty
462468
count:
463469
range: integer
464470
minimum_value: 1
465471
annotations:
466-
owl: HasValue
472+
owl: HasValue, DataProperty
467473
state:
468474
range: ActivationStateEnum
469475
annotations:
470-
owl: SomeValuesFrom
476+
owl: SomeValuesFrom, ObjectProperty
471477

472478
CollectionOfPartsWithCounts:
473479
is_a: NamedThing
474-
description: test metaclass that illustrates a complex nested multi-part structure, where a whole is defined by a collection of repeared parts in specified states
480+
description: >-
481+
test metaclass that illustrates a complex nested multi-part structure,
482+
where a whole is defined by a collection of repeated parts in specified states.
475483
slots:
476484
- has_part
477485
slot_usage:
@@ -494,6 +502,48 @@ classes:
494502
)
495503
{% endfor %}
496504
505+
CollectionOfPartsWithCounts2:
506+
is_a: NamedThing
507+
description: >-
508+
as CollectionOfPartsWithCounts but using tr function
509+
slots:
510+
- has_part
511+
slot_usage:
512+
has_part:
513+
range: PartWithCounts2
514+
inlined: true
515+
annotations:
516+
owl.template: |-
517+
{% for p in has_part %}
518+
SubClassOf( {{id}}
519+
ObjectSomeValuesFrom( BFO:0000051
520+
{{ tr(p) }}
521+
522+
)
523+
)
524+
{% endfor %}
525+
526+
PartWithCounts2:
527+
is_a: Anonymous
528+
description: test metaclass that generates anonymous classes used as part of a more complex class
529+
attributes:
530+
unit:
531+
range: NamedThing
532+
multivalued: false
533+
annotations:
534+
owl: ObjectSomeValuesFrom, ObjectProperty
535+
count:
536+
range: integer
537+
minimum_value: 1
538+
annotations:
539+
owl: DataHasValue, DataProperty
540+
state:
541+
range: ActivationStateEnum
542+
annotations:
543+
owl: ObjectSomeValuesFrom, ObjectProperty
544+
annotations:
545+
owl: IntersectionOf
546+
497547
GCIPropagationMetapattern:
498548
mixin: true
499549
description: mixin for patterns that require GCI inference

tests/output/chromo.schema.owl.ttl

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
chromoschema:GenomeBuild,
2424
chromoschema:OrganismTaxon ;
2525
dcterms:license "https://creativecommons.org/publicdomain/zero/1.0/" ;
26-
linkml:generation_date "2023-03-21T13:21:57" ;
26+
linkml:generation_date "2023-04-03T17:22:51" ;
2727
linkml:metamodel_version "1.7.0" ;
2828
linkml:source_file "chromo.yaml" ;
2929
linkml:source_file_date "2022-01-12T21:11:50" ;
@@ -44,14 +44,14 @@ chromoschema:ChromosomePartCollection a owl:Class,
4444
linkml:ClassDefinition ;
4545
rdfs:label "ChromosomePartCollection" ;
4646
rdfs:subClassOf [ a owl:Restriction ;
47-
owl:allValuesFrom chromoschema:OrganismTaxon ;
48-
owl:onProperty dcterms:hasPart ],
49-
[ a owl:Restriction ;
5047
owl:allValuesFrom chromoschema:ChromosomePart ;
5148
owl:onProperty dcterms:hasPart ],
5249
[ a owl:Restriction ;
5350
owl:allValuesFrom chromoschema:Genome ;
5451
owl:onProperty dcterms:hasPart ],
52+
[ a owl:Restriction ;
53+
owl:allValuesFrom chromoschema:OrganismTaxon ;
54+
owl:onProperty dcterms:hasPart ],
5555
[ a owl:Restriction ;
5656
owl:maxQualifiedCardinality 1 ;
5757
owl:onClass linkml:String ;
@@ -206,24 +206,24 @@ chromoschema:Genome a owl:Class,
206206
linkml:ClassDefinition ;
207207
rdfs:label "Genome" ;
208208
rdfs:subClassOf [ a owl:Restriction ;
209+
owl:allValuesFrom chromoschema:GenomeBuild ;
210+
owl:onProperty chromoschema:previous_builds ],
211+
[ a owl:Restriction ;
212+
owl:onClass linkml:String ;
213+
owl:onProperty chromoschema:id ;
214+
owl:qualifiedCardinality 1 ],
215+
[ a owl:Restriction ;
209216
owl:maxQualifiedCardinality 1 ;
210217
owl:onClass chromoschema:GenomeBuild ;
211218
owl:onProperty biolink:genome_build ],
212-
[ a owl:Restriction ;
213-
owl:maxQualifiedCardinality 1 ;
214-
owl:onClass chromoschema:TaxonIdentifier ;
215-
owl:onProperty RO:0002162 ],
216-
[ a owl:Restriction ;
217-
owl:allValuesFrom chromoschema:GenomeBuild ;
218-
owl:onProperty chromoschema:previous_builds ],
219219
[ a owl:Restriction ;
220220
owl:onClass chromoschema:LabelType ;
221221
owl:onProperty rdfs:label ;
222222
owl:qualifiedCardinality 1 ],
223223
[ a owl:Restriction ;
224-
owl:onClass linkml:String ;
225-
owl:onProperty chromoschema:id ;
226-
owl:qualifiedCardinality 1 ] ;
224+
owl:maxQualifiedCardinality 1 ;
225+
owl:onClass chromoschema:TaxonIdentifier ;
226+
owl:onProperty RO:0002162 ] ;
227227
skos:definition """Represents a sequenced genome, one per species.
228228
Each genome can be associated with one or more builds""" .
229229

@@ -233,15 +233,15 @@ chromoschema:OrganismTaxon a owl:Class,
233233
rdfs:subClassOf [ a owl:Restriction ;
234234
owl:maxQualifiedCardinality 1 ;
235235
owl:onClass chromoschema:LabelType ;
236-
owl:onProperty rdfs:label ],
236+
owl:onProperty OIO:hasExactSynonym ],
237237
[ a owl:Restriction ;
238238
owl:onClass linkml:String ;
239239
owl:onProperty chromoschema:id ;
240240
owl:qualifiedCardinality 1 ],
241241
[ a owl:Restriction ;
242242
owl:maxQualifiedCardinality 1 ;
243243
owl:onClass chromoschema:LabelType ;
244-
owl:onProperty OIO:hasExactSynonym ] ;
244+
owl:onProperty rdfs:label ] ;
245245
skos:definition "Represents a species, e.g. Homo sapiens" ;
246246
skos:exactMatch biolink:OrganismTaxon .
247247

@@ -323,69 +323,69 @@ chromoschema:ChromosomePart a owl:Class,
323323
linkml:ClassDefinition ;
324324
rdfs:label "ChromosomePart" ;
325325
rdfs:subClassOf [ a owl:Restriction ;
326-
owl:onClass linkml:String ;
327-
owl:onProperty chromoschema:id ;
328-
owl:qualifiedCardinality 1 ],
326+
owl:maxQualifiedCardinality 1 ;
327+
owl:onClass chromoschema:BandDescriptor ;
328+
owl:onProperty chromoschema:band_descriptor ],
329329
[ a owl:Restriction ;
330330
owl:maxQualifiedCardinality 1 ;
331-
owl:onClass chromoschema:LocationType ;
331+
owl:onClass chromoschema:ChromosomePart ;
332332
owl:onProperty BFO:0000050 ],
333333
[ a owl:Restriction ;
334-
owl:maxQualifiedCardinality 1 ;
335-
owl:onClass chromoschema:LabelType ;
336-
owl:onProperty rdfs:label ],
334+
owl:allValuesFrom linkml:String ;
335+
owl:onProperty OIO:hasExactSynonym ],
337336
[ a owl:Restriction ;
338337
owl:maxQualifiedCardinality 1 ;
339338
owl:onClass chromoschema:ChromosomeNameType ;
340339
owl:onProperty chromoschema:chromosome_name ],
341340
[ a owl:Restriction ;
342341
owl:maxQualifiedCardinality 1 ;
343-
owl:onClass chromoschema:BandDescriptor ;
344-
owl:onProperty chromoschema:band_descriptor ],
345-
[ a owl:Restriction ;
346-
owl:allValuesFrom linkml:Uriorcurie ;
347-
owl:onProperty skos:exactMatch ],
342+
owl:onClass chromoschema:TaxonIdentifier ;
343+
owl:onProperty RO:0002162 ],
348344
[ a owl:Restriction ;
349345
owl:maxQualifiedCardinality 1 ;
350-
owl:onClass linkml:Integer ;
351-
owl:onProperty gff:start ],
352-
[ a owl:Restriction ;
353-
owl:allValuesFrom linkml:String ;
354-
owl:onProperty OIO:hasExactSynonym ],
346+
owl:onClass chromoschema:SexChromosomeType ;
347+
owl:onProperty chromoschema:sex_chromosome_type ],
355348
[ a owl:Restriction ;
356349
owl:maxQualifiedCardinality 1 ;
357350
owl:onClass chromoschema:EntityType ;
358351
owl:onProperty rdf:type ],
352+
[ a owl:Restriction ;
353+
owl:maxQualifiedCardinality 1 ;
354+
owl:onClass linkml:Integer ;
355+
owl:onProperty gff:end ],
356+
[ a owl:Restriction ;
357+
owl:maxQualifiedCardinality 1 ;
358+
owl:onClass chromoschema:LabelType ;
359+
owl:onProperty rdfs:label ],
359360
[ a owl:Restriction ;
360361
owl:maxQualifiedCardinality 1 ;
361362
owl:onClass chromoschema:GenomeBuild ;
362363
owl:onProperty biolink:genome_build ],
363364
[ a owl:Restriction ;
364-
owl:allValuesFrom linkml:String ;
365-
owl:onProperty OIO:hasBroadSynonym ],
365+
owl:allValuesFrom chromoschema:ChromosomePart ;
366+
owl:onProperty BFO:0000051 ],
366367
[ a owl:Restriction ;
367368
owl:maxQualifiedCardinality 1 ;
368-
owl:onClass chromoschema:ChromosomePart ;
369-
owl:onProperty BFO:0000050 ],
369+
owl:onClass chromoschema:AutosomeVsSexChromosome ;
370+
owl:onProperty chromoschema:somal_type ],
370371
[ a owl:Restriction ;
371-
owl:maxQualifiedCardinality 1 ;
372-
owl:onClass chromoschema:SexChromosomeType ;
373-
owl:onProperty chromoschema:sex_chromosome_type ],
372+
owl:allValuesFrom linkml:String ;
373+
owl:onProperty OIO:hasBroadSynonym ],
374374
[ a owl:Restriction ;
375375
owl:maxQualifiedCardinality 1 ;
376-
owl:onClass chromoschema:TaxonIdentifier ;
377-
owl:onProperty RO:0002162 ],
378-
[ a owl:Restriction ;
379-
owl:allValuesFrom chromoschema:ChromosomePart ;
380-
owl:onProperty BFO:0000051 ],
376+
owl:onClass chromoschema:LocationType ;
377+
owl:onProperty BFO:0000050 ],
381378
[ a owl:Restriction ;
382379
owl:maxQualifiedCardinality 1 ;
383380
owl:onClass linkml:Integer ;
384-
owl:onProperty gff:end ],
381+
owl:onProperty gff:start ],
385382
[ a owl:Restriction ;
386-
owl:maxQualifiedCardinality 1 ;
387-
owl:onClass chromoschema:AutosomeVsSexChromosome ;
388-
owl:onProperty chromoschema:somal_type ] ;
383+
owl:onClass linkml:String ;
384+
owl:onProperty chromoschema:id ;
385+
owl:qualifiedCardinality 1 ],
386+
[ a owl:Restriction ;
387+
owl:allValuesFrom linkml:Uriorcurie ;
388+
owl:onProperty skos:exactMatch ] ;
389389
skos:definition "A Chromosome or a part of a chromosome (includes whole chromosomes, arms, and bands)" ;
390390
skos:note """OWL Notes: when translated to OWL, instances of this class will be treated as
391391
OWL classes, with the superclass determined by the type field""",
@@ -401,13 +401,13 @@ chromoschema:GenomeBuild a owl:Class,
401401
linkml:ClassDefinition ;
402402
rdfs:label "GenomeBuild" ;
403403
rdfs:subClassOf [ a owl:Restriction ;
404-
owl:onClass linkml:String ;
405-
owl:onProperty chromoschema:id ;
406-
owl:qualifiedCardinality 1 ],
407-
[ a owl:Restriction ;
408404
owl:maxQualifiedCardinality 1 ;
409405
owl:onClass chromoschema:LabelType ;
410-
owl:onProperty rdfs:label ] ;
406+
owl:onProperty rdfs:label ],
407+
[ a owl:Restriction ;
408+
owl:onClass linkml:String ;
409+
owl:onProperty chromoschema:id ;
410+
owl:qualifiedCardinality 1 ] ;
411411
skos:closeMatch edam:operation_0525 ;
412412
skos:definition "Represents a specific build of a sequenced genome" .
413413

0 commit comments

Comments
 (0)