Skip to content

Commit 8aeb4f2

Browse files
committed
refactor visu, add description, filter Ia
1 parent 5727881 commit 8aeb4f2

File tree

3 files changed

+64
-34
lines changed

3 files changed

+64
-34
lines changed

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ pydantic >= 2.4.2
1313
packaging
1414
pandas
1515
platformdirs
16+
pydot

src/pyirk/utils.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import os
22
import pyirk as p
3-
3+
from jinja2 import Environment, FileSystemLoader
44
from ipydex import IPS
55

6+
from pyirk.settings import TEMPLATE_PATH
7+
68

79
class GeneralHousekeeperMixin:
810
"""
@@ -66,3 +68,19 @@ def had_error(self):
6668

6769
error_list = [b for (a, b) in self._outcome.errors if b is not None]
6870
return bool(error_list)
71+
72+
73+
def render_template(template: str, context: dict):
74+
"""
75+
:param template: path to template file relative to TEMPLATE_DIR
76+
:param context: dict containing the data which should be inserted into the template
77+
"""
78+
jin_env = Environment(
79+
loader=FileSystemLoader(TEMPLATE_PATH),
80+
)
81+
82+
template_doc = jin_env.get_template(template)
83+
84+
res = template_doc.render(context=context)
85+
86+
return res

src/pyirk/visualization.py

Lines changed: 44 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
# TODO: this should be a relative import of the *package*
2222
import pyirk as p
23+
from pyirk.utils import render_template
2324
from ipydex import IPS, activate_ips_on_exception
2425

2526
__all__ = ["visualize_entity", "visualize_all_entities"]
@@ -437,6 +438,7 @@ def get_color_for_stm(stm: p.Statement) -> str:
437438
def create_complete_graph(
438439
url_template="",
439440
limit: Optional[int] = None,
441+
skip_auto_items: bool = False,
440442
) -> nx.DiGraph:
441443
"""
442444
:param url_template: template to insert links based on uris
@@ -460,6 +462,8 @@ def create_complete_graph(
460462
continue
461463
if not isinstance(item, p.Item) or item.short_key in ["I000"]:
462464
continue
465+
if skip_auto_items and "Ia" in item.short_key:
466+
continue
463467
# count only items
464468
i += 1
465469
if limit and i == limit:
@@ -483,6 +487,8 @@ def create_complete_graph(
483487

484488
subj, pred, obj = stm.relation_tuple
485489
if isinstance(obj, p.Item):
490+
if skip_auto_items and "Ia" in obj.short_key:
491+
continue
486492
if other_node := added_items_nodes.get(obj.uri):
487493
pass
488494
else:
@@ -504,14 +510,21 @@ def create_complete_graph(
504510
return G
505511

506512

507-
def render_graph_to_dot(G: nx.DiGraph) -> str:
513+
def render_graph_to_dot(G: nx.DiGraph, center_node=None) -> str:
508514
"""
509515
510516
:param G: nx.DiGraph; the graph to render
511517
:return: dot_data
512518
"""
513519

514520
ecm = build_edge_color_map(G)
521+
def get_node_color(node):
522+
if node.short_key.startswith("Ia"):
523+
return "grey"
524+
elif node == center_node:
525+
return "red"
526+
else:
527+
return "black"
515528

516529
# for styling see https://nxv.readthedocs.io/en/latest/reference.html#styling
517530
style = nxv.Style(
@@ -534,7 +547,7 @@ def render_graph_to_dot(G: nx.DiGraph) -> str:
534547
"height": 1.3,
535548
"shape": d.get("shape", "circle"), # see also AbstractNode.shape
536549
"style": "filled",
537-
"color": "grey" if u.short_key.startswith("Ia") else "black",
550+
"color": get_node_color(u),
538551
"fillcolor": "#eeeeeedd" if "Ia" not in u.short_key else "#dddddddd",
539552
# Label
540553
"label": u.get_dot_label(),
@@ -641,7 +654,7 @@ def visualize_entity(uri: str, url_template="", write_tmp_files: Union[bool, str
641654
raise p.InvalidURIError(msg)
642655

643656
small_G = nx.ego_graph(big_G, node_of_interest, radius, undirected=True) #! perfomance of this operation sucks
644-
raw_dot_data = render_graph_to_dot(small_G)
657+
raw_dot_data = render_graph_to_dot(small_G, node_of_interest)
645658

646659
dot_data0 = raw_dot_data
647660
for old, new in NEWLINE_REPLACEMENTS:
@@ -672,7 +685,7 @@ def get_label(entity):
672685
return res
673686

674687

675-
def visualize_all_entities(url_template="", write_tmp_files: Union[bool, str] = False) -> str:
688+
def visualize_all_entities(url_template="", write_tmp_files: Union[bool, str] = False, skip_auto_items: bool = False) -> str:
676689
"""visualize all entities loaded in datastore. output svg graph.
677690
678691
Args:
@@ -683,7 +696,7 @@ def visualize_all_entities(url_template="", write_tmp_files: Union[bool, str] =
683696
Returns:
684697
str: svg graph
685698
"""
686-
G = create_complete_graph(url_template)
699+
G = create_complete_graph(url_template, skip_auto_items=skip_auto_items)
687700

688701
print(f"Visualizing {len(G.nodes)} nodes and {len(G.edges)} edges.")
689702
ecm = build_edge_color_map(G)
@@ -779,13 +792,13 @@ def render_label(label: str):
779792
def create_interactive_graph(url_template="", output_dir="graph_site", radius=1, skip_auto_items=True, skip_existing=False):
780793
os.makedirs(output_dir, exist_ok=True)
781794

782-
G = create_complete_graph(url_template)
795+
G = create_complete_graph(url_template, skip_auto_items=skip_auto_items)
783796
print(f"Visualizing {len(G.nodes)} nodes and {len(G.edges)} edges.")
784797

785798
for node in G.nodes:
786799
node_name = node.short_key
787-
if skip_auto_items and "Ia" in node_name:
788-
continue
800+
# if skip_auto_items and "Ia" in node_name:
801+
# continue
789802
print(node_name)
790803
dot_path = os.path.join(output_dir, f"{node_name}.dot")
791804
if skip_existing and os.path.isfile(dot_path):
@@ -800,22 +813,22 @@ def create_interactive_graph(url_template="", output_dir="graph_site", radius=1,
800813
with open(cmapx_path, "r", encoding="utf-8") as f:
801814
image_map = f.read()
802815

816+
# clean image map of replacement strings
817+
image_map = re.sub(r'(?<=href=")(.+?)(\.html".+?title=")(.+?)(?=")', lambda mo: mo.group(1)+mo.group(2)+mo.group(1), image_map)
818+
desc = p.ds.items[node.uri].R2.value if p.ds.items[node.uri].R2 else ""
819+
context = {
820+
"title": node_name + " " + p.ds.items[node.uri].R1.value,
821+
"img_source": f"{node_name}.svg",
822+
"map": image_map,
823+
"desc": desc
824+
}
825+
res = render_template("node_template.html", context)
803826
with open(os.path.join(output_dir, f"{node_name}.html"), "w", encoding="utf-8") as f:
804-
f.write(f"""<!DOCTYPE html>
805-
<html>
806-
<head><title>Node {node_name}</title></head>
807-
<body>
808-
<h1>Node {node_name}</h1>
809-
<img src="{node_name}.svg" usemap="#G" alt="Subgraph of {node_name}">
810-
{image_map}
811-
<p><a href="index.html">Back to index</a></p>
812-
</body>
813-
</html>
814-
""")
827+
f.write(res)
815828

816829
# Index page
817830
dot_path = os.path.join(output_dir, "index.dot")
818-
visualize_all_entities(write_tmp_files=dot_path)
831+
visualize_all_entities(write_tmp_files=dot_path, skip_auto_items=skip_auto_items)
819832

820833
# create map
821834
cmapx_path = os.path.join(output_dir, f"index.map")
@@ -825,20 +838,18 @@ def create_interactive_graph(url_template="", output_dir="graph_site", radius=1,
825838
with open(cmapx_path, "r", encoding="utf-8") as f:
826839
image_map = f.read()
827840

841+
context = {
842+
"title": "Overview",
843+
"img_source": f"index.svg",
844+
"map": image_map,
845+
"desc": f"Total number of Nodes: {len(G.nodes)}"
846+
}
847+
res = render_template("node_template.html", context)
828848
with open(os.path.join(output_dir, f"index.html"), "w", encoding="utf-8") as f:
829-
f.write(f"""<!DOCTYPE html>
830-
<html>
831-
<head><title>Overview</title></head>
832-
<body>
833-
<h1>Overview</h1>
834-
<img src="index.svg" usemap="#G" alt="Overview">
835-
{image_map}
836-
</body>
837-
</html>
838-
""")
849+
f.write(res)
839850

840851
if __name__ == "__main__":
841-
# visualize_all_entities(write_tmp_files=True)
842-
# create_interactive_graph()
852+
# visualize_all_entities(write_tmp_files=True, skip_auto_items=True)
853+
create_interactive_graph()
843854
# nl = p.irkloader.load_mod_from_path("output.py", "nl", "nonlinear")
844-
visualize_entity("irk:/builtins#I31", write_tmp_files=True, radius=1)
855+
# visualize_entity("irk:/builtins#I31", write_tmp_files=True, radius=1)

0 commit comments

Comments
 (0)