VladimirAlexiev / rdf2rml

RDF by Example: rdfpuml for True RDF Diagrams, rdf2rml for R2RML Generation
39 stars 5 forks source link

Fails on rdf:type with anonymous node #10

Closed johanwk closed 2 years ago

johanwk commented 2 years ago

(Running with Strawberry Perl on Windows 10.)

I find that the tool fails to produce a diagram with a common OWL pattern: when an individual is a member of an anonymous class. The error message is

Can't locate object method "uri_value" via package "RDF::Trine::Node::Blank" at bin/rdf2rml/bin/rdfpuml.pl line 275.

Here is an example that fails (from https://rds.posccaesar.org/ontology/plm/rdl/PCA_100003953/):

rdl:PCA_100003953  a  owl:NamedIndividual , lis:Scale ;

## the next "a", i.e., rdf:type, seems to be the problem ##
        a           [ a                  owl:Restriction ;
                      owl:allValuesFrom  rdl:PCA_100003891 ;
                      owl:onProperty     [ owl:inverseOf  lis:datumUOM ]
                    ] ;
        rdfs:label  "radian per second squared" ;
        om:symbol   "rad/s2" .

If the a on the second line in this example is replaced with, e.g., :x, the diagram is produced. So, I guess this has to do with some special handling of rdf:type.

VladimirAlexiev commented 2 years ago

@johanwk Yes, it always inlines rdf:type (and shows them in a comma-separated list when multiple). That works for named types but not for "constructed" types as in your example...

Will this work:

VladimirAlexiev commented 2 years ago

Will this work: https://github.com/VladimirAlexiev/rdf2rml/blob/master/test/issue10/example.puml

johanwk commented 2 years ago

I think, yes, this would work, and be useful.

Maybe it would be possible to do more, by working with the fact that owl:Restriction has a very particular meaning. The snippet I used for illustration says (abbreviating a bit), the individual PCA3953 can only have (inverse datumUOM) to members of PCA3891. It's a universal constraint on that individual. So my thinking is, it would be better if owl:Restriction and owl:onProperty could be hidden in the output diagram. Of course, this may be in conflict with what you are aiming for.

VladimirAlexiev commented 2 years ago

@johanwk Please take example.puml, load it to http://www.plantuml.com/plantuml/ and tweak it to show how you'd prefer things.

I don't know how to show Manchester notation as a graph :-)

@cmungall had a simplified notation where all/some are placed as RDF-star annotations. Chris, was it called "OWL as RDF"?

johanwk commented 2 years ago

Will this work: https://github.com/VladimirAlexiev/rdf2rml/blob/master/test/issue10/example.png

Surely, this works -- it makes a big difference, since the diagram now includes vital information that was missing before.

I'll be interested in hearing your opinion on the idea of prettifying the diagram by hiding/compacting the owl:Restriction + owl:onProperty combo.

VladimirAlexiev commented 2 years ago

hiding/compacting

I can think to implement this if you show exactly what you mean. But it should work in more generic situations (in the examples below, think of an individual attached to the starting class).

Eg

:classX rdfs:subClassOf [a owl:Restriction; owl:onProperty :propP; owl:allValuesFrom  :classY]
:classX rdfs:subClassOf [a owl:Restriction; owl:onProperty :propP; owl:someValuesFrom :classY]

or even:

ont:CTODEV18198000  a        owl:Class ;
        rdfs:label           "macula densa epithelial cell"@en ;
        rdfs:subClassOf      ont:CTODEV70164000 , ont:CTODEV54509000 ;
        rdfs:subClassOf      [ a                   owl:Class ;
                               owl:intersectionOf  ( [ a                   owl:Restriction ;
                                                       owl:onProperty      properties_populous_tutorial_SWAT4LS2011:participates_in ;
                                                       owl:someValuesFrom  GO:GO_0003093
                                                     ]
                                                     [ a                   owl:Restriction ;
                                                       owl:onProperty      properties_populous_tutorial_SWAT4LS2011:participates_in ;
                                                       owl:someValuesFrom  GO:GO_0003098
                                                     ]
                                                   )
                             ] ;
        rdfs:subClassOf      [ a                   owl:Class ;
                               owl:intersectionOf  ( [ a                   owl:Restriction ;
                                                       owl:onProperty      properties_populous_tutorial_SWAT4LS2011:has_phenotypic_quality ;
                                                       owl:someValuesFrom  PATO:PATO_0001407
                                                     ]
                                                   )
                             ] ;
        owl:equivalentClass  [ a                   owl:Class ;
                               owl:intersectionOf  ( obo:CL_0000000
                                                     [ a                   owl:Class ;
                                                       owl:intersectionOf  ( [ a                   owl:Restriction ;
                                                                               owl:onProperty      OBO_REL:part_of ;
                                                                               owl:someValuesFrom  obo:UBERON_0002335
                                                                             ]
                                                                           )
                                                     ]
                                                   )
                             ] .
johanwk commented 2 years ago

Clever people have tried to solve this before, and failed ;) It's quite a challenge, as you indicate, to find the right balance. But I'll at least try to show something with the example you provided -- many thanks!

johanwk commented 2 years ago

How about this?

'class _r1658327087r0_ as " "
'_r1658327087r0_ : a owl:Restriction
class rdl_PCA_100003891 as "rdl:PCA_100003891"
_r1658327087r1_ -down-> rdl_PCA_100003891 : owl:allValuesFrom
class _r1658327087r1_ as " "
'_r1658327087r0_ -down-> _r1658327087r1_ : owl:onProperty
class lis_datumUOM as "lis:datumUOM"
_r1658327087r1_ -right-> lis_datumUOM : owl:inverseOf
class rdl_PCA_100003953 as "rdl:PCA_100003953"
rdl_PCA_100003953 : a owl:NamedIndividual, lis:Scale
rdl_PCA_100003953 -down-> _r1658327087r1_ : rdfs:type1
rdl_PCA_100003953 : om:symbol "rad/s2"
rdl_PCA_100003953 : rdfs:label "radian per second squared"

example

johanwk commented 2 years ago

Another "improvement" (depending on who's looking) would be to pull out rdfs:label, to make the diagram more readable:

'class _r1658327087r0_ as " "
'_r1658327087r0_ : a owl:Restriction
class rdl_PCA_100003891 as "angular acceleration datum\nrdl:PCA_100003891"
_r1658327087r1_ -down-> rdl_PCA_100003891 : owl:allValuesFrom
class _r1658327087r1_ as " "
'_r1658327087r0_ -down-> _r1658327087r1_ : owl:onProperty
class lis_datumUOM as "lis:datumUOM"
_r1658327087r1_ -right-> lis_datumUOM : owl:inverseOf
class rdl_PCA_100003953 as "radian per second squared\nrdl:PCA_100003953"
rdl_PCA_100003953 : a owl:NamedIndividual, lis:Scale
rdl_PCA_100003953 -down-> _r1658327087r1_ : rdfs:type1
rdl_PCA_100003953 : om:symbol "rad/s2"
'rdl_PCA_100003953 : rdfs:label "radian per second squared"

example

johanwk commented 2 years ago

... maybe even like this:

class rdl_PCA_100003891 as "angular acceleration datum\nrdl:PCA_100003891"
class _r1658327087r1_ as " "
_r1658327087r1_ -down-> rdl_PCA_100003891 : owl:allValuesFrom
class lis_datumUOM as "lis:datumUOM"
_r1658327087r1_ -right-> lis_datumUOM : owl:inverseOf
class rdl_PCA_100003953 as "radian per second squared\nrdl:PCA_100003953"
rdl_PCA_100003953 : a owl:NamedIndividual, lis:Scale
rdl_PCA_100003953 -down- _r1658327087r1_ : owl:Restriction owl:onProperty
rdl_PCA_100003953 : om:symbol "rad/s2"

example

cmungall commented 2 years ago

@VladimirAlexiev:

@cmungall had a simplified notation where all/some are placed as RDF-star annotations. Chris, was it called "OWL as RDF"?

https://github.com/cmungall/owlstar

It is perhaps not the best name as it's independent of RDF-star, as it uses simple RDF reification

johanwk commented 2 years ago

Will this work: https://github.com/VladimirAlexiev/rdf2rml/blob/master/test/issue10/example.puml

Coming back to this, I'm thinking that your initial proposal is probably the best!

VladimirAlexiev commented 2 years ago

@johanwk @cmungall if I apply maximum inlining (https://github.com/VladimirAlexiev/rdf2rml/tree/master/test/issue10), here are the two examples.

Yours

image

Mine

image

It's the best we can do. Would be nice to display rdf:Lists better, but see #11.

Notice in prefixes.ttl, so I'll appreciate if you do some more tests (ideally submit PR, if not post code here).

# these props are inlined only if they carry a constant node, not if they carry a blank node. 
# (It's a happy coincidence, I can't guarantee that happens in all cases)
owl:onProperty      a puml:InlineProperty.
owl:someValuesFrom  a puml:InlineProperty.
owl:allValuesFrom   a puml:InlineProperty.
owl:inverseOf       a puml:InlineProperty.
rdf:first           a puml:InlineProperty.
rdf:rest            a puml:InlineProperty.

In your tests, use rdf:type1 instead of rdf:type (or a). I'll now work to change the script to handle the standard prop rdf:type.