The PROV-O ontology is a standard for representing provenance information. The primer contains conventions to visualize provenance graphs.
The core classes are prov:Entity
, prov:Activity
, and prov:Agent
.
Each instance should be rendered as a node with a specific shape and color. This is easily achieved
with N3 rules:
{
?entity a prov:Entity
}
=>
{
v:digraph v:hasNode ?entity .
?entity attr:shape "oval" ;
attr:color "#808080" ;
attr:style "filled" ;
attr:fillcolor "#FFFC87" .
} .
{
?activity a prov:Activity
}
=>
{
v:digraph v:hasNode ?activity .
?activity attr:shape "box" ;
attr:color "blue" ;
attr:style "filled" ;
attr:fillcolor "#9FB1FC" .
} .
{
?agent a prov:Agent
}
=>
{
v:digraph v:hasNode ?agent .
?agent attr:shape "house" ;
attr:color "black" ;
attr:style "filled" ;
attr:fillcolor "#FED37F" .
} .
Two additional rules provide a short node label (extracted from the URI) and a clickable link for dereferencing the URI:
{ v:digraph v:hasNode ?n . ?n log:localName ?localName } => { ?n attr:label ?localName } .
{ v:digraph v:hasNode ?n . ?n log:uri ?uri } => { ?n attr:URL ?uri } .
The following triples:
ex:dataset1 a prov:Entity .
ex:compose1 a prov:Activity .
ex:derek a prov:Agent .
produce the following nodes:
Edges are created between nodes related by predicates in the PROV-O namespace:
{
v:digraph v:hasNode ?n1, ?n2 .
?n1 ?p ?n2 .
?p log:namespace "http://www.w3.org/ns/prov#";
log:uri ?uri ;
log:localName ?localName .
}
=>
{
v:digraph v:hasEdge [
v:source ?n1;
v:target ?n2 ;
attr:label ?localName ;
attr:labelURL ?uri ;
attr:tooltip ?uri
]
} .
The convention gives also layout indications, so we can add the following rule
to enforce bottom-to-top:
{} => { v:digraph v:graphAttributes [ attr:rankdir "BT" ] } .
The rendering of this example from the specification looks very similar to the original:
Some PROV-O relations can be qualified with a role. Instead of a simple prov:used
relationship
between an activity and an entity,
it's possible to have a prov:qualifiedUsage
link to a prov:Usage
node having a
prov:hadRole
property:
ex:dataset1 a prov:Entity .
ex:compose1 a prov:Activity .
ex:compose1 prov:qualifiedUsage [
a prov:Usage ;
prov:entity ex:dataset1 ;
prov:hadRole ex:dataToCompose
] .
In the conventional rendering, the activity and the entity are directly connected by an edge with label
used
,
and this edge has an outgoing dashed edge to a note-shaped node labeled with the role.
Graphviz does not support edges pointing at other
edges,
but we can use a small invisible node to achieve a similar effect:
{
?activity prov:qualifiedUsage [ prov:entity ?entity ; prov:hadRole ?role ] .
?role log:localName ?roleName .
("prov:hadRole=\n" ?roleName) string:concatenation ?roleLabel .
}
=>
{
_:hidden attr:shape "point"; attr:width "0"; attr:height "0"; attr:xlabel "used" .
v:digraph v:hasNode _:hidden .
v:digraph v:hasEdge [ v:source ?activity; v:target _:hidden; attr:dir "none"] .
v:digraph v:hasEdge [ v:source _:hidden; v:target ?entity] .
_:role attr:shape "note"; attr:label ?roleLabel .
v:digraph v:hasNode _:role .
v:digraph v:hasEdge [ v:source _:hidden; v:target _:role; attr:dir "none"; attr:style "dashed"] .
} .
While the hidden intermediate node makes the edge not as smooth as desired, we still obtain a visualization close enough to the original
The full set of PROV-O visualization rules is available in the repo. You can load that .n3 file as custom rules in the playground tool to visualize your own PROV-O datasets.