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

[Blocked by #127] GH-125: Update assumptions and correct type handling. #126

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion src/ipyradiant/rdf2nx/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ def transform_nodes(

if node_iris is None:
# TODO paginate (LIMIT+OFFSET) for batch processing?
node_iris = list(cls.query_manager(cls.node_iris, rdf_graph)["iri"])
# node_iris = list(cls.query_manager(cls.node_iris, rdf_graph)["iri"])
node_iris = list(rdf_graph.subjects())

for node_iri in node_iris:
# TODO this isn't actually used (should it be?)
Expand Down
2 changes: 1 addition & 1 deletion src/ipyradiant/rdf2nx/edges.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class RelationTypes(SPARQLQueryFramer):
# Plain relations, non-reified
?source ?predicate ?target.

FILTER ( isIRI ( ?target ) ). # prevent bad things
FILTER ( !isLiteral( ?target ) ). # prevent bad things

# Plain relations must get their fictitious IRI from constructs like this.
# Using the triple components ensures a unique IRI identifying the triple.
Expand Down
29 changes: 23 additions & 6 deletions src/ipyradiant/visualization/cytoscape/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pandas import DataFrame
from rdflib.graph import Graph as RDFGraph
from rdflib.term import URIRef
from rdflib.namespace import OWL

from ipyradiant.basic_tools.custom_uri_ref import CustomURIRef
from ipyradiant.rdf2nx.converter import RDF2NX
Expand Down Expand Up @@ -56,6 +57,9 @@ def get_color_list_css(color_list):

def get_desc(uri, namespaces, count=None):
"""Get a shorthand way to describe a URI and its counts."""
if type(uri) is not URIRef:
# just return the string
return str(uri)

shorthand = str(CustomURIRef(uri, namespaces=namespaces))
if count:
Expand All @@ -67,9 +71,11 @@ def get_type_counts(klass, graph: NXGraph) -> DataFrame:
type_dict = {}
for node, data in graph.nodes(data=True):
# node_type can be a list (make all list)
type_attr = data.get("rdf:type")
type_attr = data.get("rdf:type") or data.get("rdfs:subClassOf")
if not type_attr:
raise ValueError(f"Node has no 'rdf:type': {data.keys()}")
# TODO logging
# raise ValueError(f"Node has no 'rdf:type': {data.keys()}")
type_attr = "Blank Node"

if not isinstance(type_attr, (list, tuple)):
node_types = [
Expand Down Expand Up @@ -189,7 +195,7 @@ def assign_css_classes(self):
color_list = COLOR_LIST.copy()
n_to_add = len(self.uri_to_string_type.keys()) - len(color_list)
if n_to_add > 0 and self.allow_large_graphs:
color_list.extend([(255, 255, 255)] * n_to_add)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was white and made the nodes basically invisible

color_list.extend([(220, 220, 220)] * n_to_add)
elif n_to_add > 0:
raise ValueError(
f"Cannot render more than {len(COLOR_LIST)} visually distinct colors."
Expand Down Expand Up @@ -244,7 +250,8 @@ def update_classes(self, change):

if change_type in {"node_type", "both"}:
for node in self.viewer.cytoscape_widget.graph.nodes:
raw_types = node.data["rdf:type"]
# TODO improve coloring after this
raw_types = node.data.get("rdf:type") or node.data.get("rdfs:subClassOf")
types = raw_types if type(raw_types) is tuple else (raw_types,)
if not any([_type in visible_node_types for _type in types]):
node.classes = "invisible"
Expand Down Expand Up @@ -279,10 +286,19 @@ def apply_node_styling(self, change):
# assign CSS classes to nodes based on their rdf:type
# TODO add types instead of replacing once we figure out how to make partial matches of css classes in ipycytoscape
for node in self.viewer.cytoscape_widget.graph.nodes:
node_types = node.data.get("rdf:type", [])
node_types = (
node.data.get("rdf:type") or
node.data.get("rdfs:subClassOf") or
[]
)
if type(node_types) == URIRef:
node_types = (node_types,)

# Remove instance type for coloring
node_types_pruned = set(node_types)
node_types_pruned.discard(OWL.NamedIndividual)
node_types = tuple(node_types_pruned,)

if len(node_types) == 1:
# assign specific class to node
assert node_types[0] in self.uri_to_string_type
Expand Down Expand Up @@ -386,7 +402,8 @@ def update_rdf_graph(self, change):
uri: str(CustomURIRef(uri, namespaces=rdf_graph.namespace_manager)).replace(
":", "-"
)
for uri in type_count.type_
if type(uri) is URIRef else str(uri)
for uri in type_count.type_
}
self.uri_to_string_type["multi-type"] = "multi-type"

Expand Down