Skip to content

Commit

Permalink
add dict kwargs for interactive styling
Browse files Browse the repository at this point in the history
  • Loading branch information
chrishavlin committed May 30, 2024
1 parent 11fe7c1 commit 032205f
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 11 deletions.
108 changes: 108 additions & 0 deletions docs/examples/ex_006_interactive_graph_styles.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "02cf8f5a-7b49-42aa-9689-74c015b9264a",
"metadata": {},
"outputs": [],
"source": [
"from yt.frontends import *\n",
"from yt.data_objects.static_output import Dataset\n",
"from inheritance_explorer import ClassGraphTree\n",
"\n",
"cgt = ClassGraphTree(Dataset, funcname='_parse_parameter_file')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "a70029ac-5a0a-4c13-bcbe-03536f8e086b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"_tmp.html\n"
]
},
{
"data": {
"text/html": [
"\n",
" <iframe\n",
" width=\"500px\"\n",
" height=\"500px\"\n",
" src=\"_tmp.html\"\n",
" frameborder=\"0\"\n",
" allowfullscreen\n",
" \n",
" ></iframe>\n",
" "
],
"text/plain": [
"<IPython.lib.display.IFrame at 0x7ff8451998d0>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"node_style = {'size': 20.0, 'color':'magenta'}\n",
"edge_style = {'weight': 5}\n",
"sim_style = {'color': (.5, 1., 1.), 'weight':5}\n",
"graph = cgt.build_interactive_graph(width=\"500px\",\n",
" height=\"500px\",\n",
" bgcolor=(0.98,.98,.98),\n",
" font_color='black', \n",
" node_style=node_style, \n",
" edge_style = edge_style,\n",
" similarity_edge_style=sim_style, \n",
" override_node_color='black',\n",
" cdn_resources='in_line'\n",
" ) \n",
"graph.show('_tmp.html')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7fba449e-7f99-40b7-9cb8-fd0df2f17f79",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "bc78a8f2-1acb-4d42-9a19-64fbea5842a4",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
78 changes: 67 additions & 11 deletions inheritance_explorer/inheritance_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,13 @@ def plot_similarity(
return sim_labels, ax

def build_interactive_graph(
self, include_similarity: bool = True, **kwargs
self,
include_similarity: bool = True,
node_style: dict = None,
edge_style: dict = None,
similarity_edge_style: dict = None,
override_node_color: Union[str, tuple] = None,
**kwargs,
) -> Network:

"""
Expand All @@ -356,6 +362,19 @@ def build_interactive_graph(
any arg accepted by pydot.Dot
include_similarity: bool
include edges for similar code (default True)
node_style: dict
a dictionary of parameters to pass to pyvis.network.Network.add_node
note that these settings will be applied to **all** nodes.
edge_style: dict
a dictionary of parameters to pass to pyvis.network.Network.add_edge
note that these settings will be applied to **all** edges.
similarity_edge_style: dict
a dictionary of parameters to pass to pyvis.network.Network.add_edge
for the similarity links. Only used if include_similarity is True.
override_node_color: str or tuple
the color for nodes that over-ride the function being tracked. Only
used if the base ClassGraphTree was initialized with a ``funcname``
to track.
**kwargs:
any additional keyword arguments are passed to graphviz.Digraph(**kwargs)
Expand All @@ -365,15 +384,37 @@ def build_interactive_graph(
the pyvis.Network representation of the class hierarchy.
"""

if node_style is None:
node_style = {}
if edge_style is None:
edge_style = {}
if similarity_edge_style is None:
similarity_edge_style = {}

sim_node_physics = similarity_edge_style.pop("physics", False)
edge_physics = edge_style.pop("physics", True)

node_color = _validate_color(node_style.get("color", None), (0.7, 0.7, 0.7))
edge_color = _validate_color(edge_style.pop("color", None), (0.7, 0.7, 0.7))
sim_edge_color = _validate_color(
similarity_edge_style.pop("color", None), (0, 0.5, 1.0)
)
override_color = _validate_color(override_node_color, (0.5, 0.5, 1.0))

bgcolor = _validate_color(kwargs.pop("bgcolor", None), (1.0, 1.0, 1.0))
font_color = _validate_color(kwargs.pop("font_color", None), (0.0, 0.0, 0.0))

grph = nx.Graph(directed=True)

iset = 0
for node in self._node_list:
if node.color == "#000000":
# no override. show improve this...
hexcolor = rgb2hex((0.7, 0.7, 0.7))
# this node is over-ridden, use over-ride color
clr_val = override_color
else:
hexcolor = rgb2hex((0.5, 0.5, 1.0))
clr_val = node_color

node_style["color"] = clr_val

if node.parent:
parent_info = f"({node.parent.__name__})"
Expand All @@ -382,33 +423,37 @@ def build_interactive_graph(
grph.add_node(
node.child_id,
title=f"{node.child_name}{parent_info}",
color=hexcolor,
**node_style,
)

if include_similarity:
if int(node.child_id) in self.similarity_sets:
hexcolor = rgb2hex((0, 0.5, 1.0))
iset += 1
for similar_node_id in self.similarity_sets[int(node.child_id)]:
grph.add_edge(
node.child_id,
str(similar_node_id),
color=hexcolor,
physics=False,
color=sim_edge_color,
physics=sim_node_physics,
**similarity_edge_style,
)

arrowsop = {"from": {"enabled": True}}

if node.parent:
grph.add_edge(
node.child_id,
node.parent_id,
color=rgb2hex((0.7, 0.7, 0.7)),
physics=True,
color=edge_color,
physics=edge_physics,
arrows=arrowsop,
**edge_style,
)

# return the interactive pyvis Network graph
network_wrapper = Network(notebook=True, **kwargs)
network_wrapper = Network(
notebook=True, bgcolor=bgcolor, font_color=font_color, **kwargs
)
network_wrapper.from_nx(grph)
return network_wrapper

Expand Down Expand Up @@ -473,6 +518,17 @@ def display_code_comparison(self):
display_code_compare(self)


def _validate_color(clr, default_rgb_tuple: tuple) -> str:
if clr is None:
return rgb2hex(default_rgb_tuple)
elif isinstance(clr, tuple):
return rgb2hex(clr)
elif isinstance(clr, str):
return clr
msg = f"clr has unexpected type: {type(clr)}"
raise TypeError(msg)


def _show_graph(dot_graph: pydot.Dot, format: str = "svg", env: str = "notebook"):
# return a GraphViz dot graph in a jupyter-friendly format.
create_func = getattr(dot_graph, f"create_{format}")
Expand Down
17 changes: 17 additions & 0 deletions inheritance_explorer/tests/test_inheritance_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,23 @@ def test_interactive(cgt):
_ = cgt.show_graph(env=None)


def test_interactive_styles(cgt):
node_style = {"size": 20.0, "color": "magenta"}
edge_style = {"weight": 5}
sim_style = {"color": (0.5, 1.0, 1.0), "weight": 5}
_ = cgt.build_interactive_graph(
width="500px",
height="500px",
bgcolor=(0.98, 0.98, 0.98),
font_color="black",
node_style=node_style,
edge_style=edge_style,
similarity_edge_style=sim_style,
override_node_color="black",
cdn_resources="in_line",
)


@pytest.mark.parametrize("max_recursion_level", (0, 1))
def test_recursion_level(max_recursion_level):
cgt = ClassGraphTree(
Expand Down

0 comments on commit 032205f

Please sign in to comment.