Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use new omero-marshal context #30

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ dependencies = [
"rdflib",
"pyld",
"rdflib-pyld-compat",
"omero-marshal",
"omero-marshal @ git+https://github.com/joshmoore/omero-marshal#new-context",
"wikidataintegrator",
"packaging"
"packaging",
"setuptools",
]

classifiers = [
Expand Down
74 changes: 32 additions & 42 deletions src/omero_rdf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import logging
from argparse import Namespace
from functools import wraps
from typing import Any, Callable, Dict, Generator, List, Optional, Set, Tuple, Union
from typing import Any, Callable, Dict, Generator, List, Set, Tuple, Union

from importlib.metadata import entry_points
from omero.cli import BaseControl, Parser, ProxyStringType
Expand All @@ -36,7 +36,7 @@
from omero_marshal import get_encoder
from pyld import jsonld
from rdflib import BNode, Graph, Literal, URIRef
from rdflib.namespace import DCTERMS, RDF
from rdflib.namespace import DCTERMS, Namespace as NS, RDF
from rdflib_pyld_compat import pyld_jsonld_from_rdflib_graph

HELP = """A plugin for exporting RDF from OMERO
Expand Down Expand Up @@ -67,6 +67,11 @@
Triple = Tuple[Subj, URIRef, Obj]
Handlers = List[Callable[[URIRef, URIRef, Data], Generator[Triple, None, bool]]]

# NAMESPACE DEFINITIONS

NS_OME = NS("http://www.openmicroscopy.org/Schemas/OME/2016-06#")
NS_OMERO = NS("http://www.openmicroscopy.org/Schemas/OMERO/2016-06#")


@contextlib.contextmanager
def open_with_default(filename=None, filehandle=None):
Expand Down Expand Up @@ -174,23 +179,19 @@ def __init__(self):
super().__init__()

def serialize_triple(self, triple):
s, p, o = triple
escaped = o.n3().encode("unicode_escape").decode("utf-8")
return f"""{s.n3()}\t{p.n3()}\t{escaped} ."""
graph = Graph()
graph.add(triple)
return graph.serialize(format="nt11")


class NonStreamingFormat(Format):
def __init__(self):
super().__init__()
self.streaming = False
self.graph = Graph()
self.graph.bind("wd", "http://www.wikidata.org/prop/direct/")
self.graph.bind("ome", "http://www.openmicroscopy.org/rdf/2016-06/ome_core/")
self.graph.bind(
"ome-xml", "http://www.openmicroscopy.org/Schemas/OME/2016-06#"
) # FIXME
self.graph.bind("omero", "http://www.openmicroscopy.org/TBD/omero/")
# self.graph.bind("xs", XMLSCHEMA)
self.graph.bind("", NS_OME)
self.graph.bind("omero", NS_OMERO)
self.graph.bind("dcterms", DCTERMS)
# TODO: Allow handlers to register namespaces

def add(self, triple):
Expand All @@ -215,11 +216,9 @@ def __init__(self):
def context(self):
# TODO: allow handlers to add to this
return {
"@wd": "http://www.wikidata.org/prop/direct/",
"@ome": "http://www.openmicroscopy.org/rdf/2016-06/ome_core/",
"@ome-xml": "http://www.openmicroscopy.org/Schemas/OME/2016-06#",
"@omero": "http://www.openmicroscopy.org/TBD/omero/",
"@idr": "https://idr.openmicroscopy.org/",
"@vocab": str(NS_OME),
"omero": str(NS_OMERO),
"dcterms": str(DCTERMS),
}

def serialize_graph(self) -> None:
Expand Down Expand Up @@ -284,9 +283,6 @@ class Handler:

"""

OME = "http://www.openmicroscopy.org/rdf/2016-06/ome_core/"
OMERO = "http://www.openmicroscopy.org/TBD/omero/"

def __init__(
self,
gateway: BlitzGateway,
Expand Down Expand Up @@ -341,16 +337,6 @@ def get_bnode(self) -> BNode:
finally:
self.bnode += 1

def get_key(self, key: str) -> Optional[URIRef]:
if key in ("@type", "@id", "omero:details", "Annotations"):
# Types that we want to omit fo
return None
else:
if key.startswith("omero:"):
return URIRef(f"{self.OMERO}{key[6:]}")
else:
return URIRef(f"{self.OME}{key}")

def get_type(self, data: Data) -> str:
return data.get("@type", "UNKNOWN").split("#")[-1]

Expand Down Expand Up @@ -384,7 +370,8 @@ def __call__(self, o: BlitzObjectWrapper) -> URIRef:
if encoder is None:
raise Exception(f"unknown: {c}")
else:
data = encoder.encode(o)
# TODO: could potentially do this once for the top object
data = encoder.encode(o, include_context=False)
return self.handle(data)

def handle(self, data: Data) -> URIRef:
Expand Down Expand Up @@ -452,16 +439,21 @@ def rdf(
for k, v in sorted(data.items()):

if k == "@type":
yield (_id, RDF.type, URIRef(v))
if v.startswith("http"):
yield (_id, RDF.type, URIRef(v))
elif v.startswith("omero:"):
yield (_id, RDF.type, NS_OMERO[v])
else:
yield (_id, RDF.type, NS_OME[v])
elif k in ("@id", "omero:details", "Annotations"):
# Types that we want to omit for now
pass
else:

# Refactor back to get_key? TODO
if k.startswith("omero:"):
key = URIRef(f"{self.OMERO}{k[6:]}")
key = NS_OMERO[k[6:]]
else:
key = URIRef(f"{self.OME}{k}")
key = NS_OME[k]

if isinstance(v, dict):
# This is an object
Expand All @@ -483,15 +475,15 @@ def rdf(
elif isinstance(item, list) and len(item) == 2:
bnode = self.get_bnode()
# TODO: KVPs need ordering info, also no use of "key" here.
yield (_id, URIRef(f"{self.OME}Map"), bnode)
yield (_id, NS_OME["Map"], bnode)
yield (
bnode,
URIRef(f"{self.OME}Key"),
NS_OME["Key"],
self.literal(item[0]),
)
yield (
bnode,
URIRef(f"{self.OME}Value"),
NS_OME["Value"],
self.literal(item[1]),
)
else:
Expand All @@ -505,15 +497,13 @@ def rdf(

handled = False
for ah in self.annotation_handlers:
handled = yield from ah(
_id, URIRef(f"{self.OME}annotation"), annotation
)
handled = yield from ah(_id, NS_OME["annotation"], annotation)
if handled:
break

if not handled: # TODO: could move to a default handler
aid = self.get_identity("AnnotationTBD", annotation["@id"])
yield (_id, URIRef(f"{self.OME}annotation"), aid)
yield (_id, NS_OME["annotation"], aid)
yield from self.rdf(aid, annotation)

def yield_object_with_id(self, _id, key, v):
Expand Down