nxontology
nxontology copied to clipboard
More general subgraph visualization utility
The current visualization function create_similarity_graphviz
is specific to visualizing the similarity between two nodes.
It's common that the user has a known subset of nodes for which they'd like to visualize the subgraph. Some flexibility is needed to allow users to pick how they'd like to label nodes and to apply additional styling. So proposing utility functions to help create subgraphs for graphviz visualizations.
Some existing code below that might be helpful
Expand for code
# code used to create figures at https://github.com/EBISPOT/efo/issues/926#issuecomment-760366239
from nxontology import NXOntology
from typing import Iterable
from nxontology.ontology import Node
from nxontology.viz import get_hex_color
from networkx.drawing.nx_agraph import to_agraph
from pygraphviz.agraph import AGraph
from IPython.display import Image
def create_subgraph_for_graphviz(
nxo: NXOntology,
nodes: Iterable[Node],
) -> "NXOntology":
nodes = set(nodes)
# independent shallow copy: creates new independent attribute dicts
subgraph = nxo.graph.subgraph(nodes).copy()
# node labels and fill/font colors
for node, data in subgraph.nodes(data=True):
info = nxo.node_info(node)
if info.label:
data["label"] = info.name
if info.identifier:
data["tooltip"] = info.identifier
if info.url:
data["URL"] = info.url
return subgraph
def create_graphviz(
nxo: NXOntology,
nodes: Iterable[Node],
outline_nodes: Iterable[Node],
keyword: str,
) -> "AGraph":
nodes = set(nodes)
outline_nodes = set(outline_nodes)
subgraph = create_subgraph_for_graphviz(nxo, nodes)
for node, data in subgraph.nodes(data=True):
data["style"] = "filled"
info = nxo.node_info(node)
data["label"] = (
f"<{info.name}<br/>"
'<font point-size="9">'
f"{info.n_descendants:,} descendants · IC<sub>res</sub> {info.intrinsic_ic_scaled:.2f}"
"</font>>"
)
scaled_ic = info.intrinsic_ic_scaled
data["fillcolor"] = get_hex_color(scaled_ic)
data["fontcolor"] = "#ffffff" if scaled_ic > 0.7 else "#000000"
# node styles
for node in nodes - outline_nodes:
subgraph.nodes[node]["penwidth"] = 1.0
for node in nodes & outline_nodes:
subgraph.nodes[node]["penwidth"] = 4.0
subgraph.nodes[node]["color"] = "#b400b4"
subgraph.nodes[node]["style"] += ",solid"
# title
subgraph.graph["label"] = f"Nodes {keyword} by EFO-OTAR (purple online) and their ancestors"
subgraph.graph["labelloc"] = "t"
# raster resolution
subgraph.graph["dpi"] = 125
gviz = to_agraph(subgraph)
gviz.layout("dot")
return gviz
# elsewhere have found wrapped names in labels is helpful
import textwrap
name_wrapped = "<br/>".join(textwrap.wrap(info.name, width=10, break_long_words=False))
# and finally to plot in a Jupyter notebook
Image(gviz.draw(format="png"))