Added blocks in data and introduced layers in Graph. Layers not in use yet and other plans added in comments.
116 lines
3.6 KiB
Python
116 lines
3.6 KiB
Python
|
|
import os
|
|
import uuid
|
|
|
|
HEADER = """
|
|
graph {
|
|
graph [splines=ortho, nodesep=1]
|
|
node [color=white]
|
|
edge [headport=n, tailport=s]
|
|
compound=true
|
|
|
|
"""
|
|
|
|
FOOTER = """
|
|
}
|
|
"""
|
|
|
|
# TODO:
|
|
# Add hidden nodes in each cluster above visible nodes connected by hidden edges and attach visible edges to them
|
|
# Solve layering of clusters
|
|
|
|
class Graph:
|
|
def __init__(self):
|
|
self.layers = {}
|
|
self.blocks = {}
|
|
self.nodes = []
|
|
self.links = {}
|
|
self.dot_file = ""
|
|
|
|
def __str__(self):
|
|
return self.dot_file
|
|
|
|
def get_id(self):
|
|
return "id" + str(uuid.uuid4().hex)
|
|
|
|
def process_blocks(self, data):
|
|
blocks = data.get('blocks', [])
|
|
|
|
for block in blocks:
|
|
block_id = self.get_id()
|
|
|
|
new_block = {
|
|
"label": block.get("label", ""),
|
|
#"layer": block.get("layer", 0),
|
|
"texts": []
|
|
}
|
|
|
|
#layer = block.get("layer", 0)
|
|
#if layer not in self.layers:
|
|
# self.layers[layer] = []
|
|
|
|
for text in block.get("texts", []):
|
|
node_id = self.get_id()
|
|
self.nodes.append({"id": node_id, "text": text.get("text", "")})
|
|
new_block["texts"].append(node_id)
|
|
#self.layers[layer].append(node_id)
|
|
|
|
links = text.get("links", {})
|
|
if links != {}:
|
|
from_links = links.get("from", [])
|
|
to_links = links.get("to", [])
|
|
for from_link in from_links:
|
|
self.links[from_link] = {"from": node_id, "to": "", "head": ""}
|
|
for to_link in to_links:
|
|
if to_link in self.links:
|
|
self.links[to_link]["to"] = node_id
|
|
self.links[to_link]["head"] = block_id
|
|
|
|
self.blocks[block_id] = new_block
|
|
|
|
def build_dot(self):
|
|
self.dot_file = HEADER
|
|
|
|
for node in self.nodes:
|
|
self.dot_file += f"{node['id']} [label=\"{node['text']}\"]\n"
|
|
self.dot_file += "\n"
|
|
|
|
for block_id, block in self.blocks.items():
|
|
self.dot_file += f"subgraph cluster_{block_id} {{\n"
|
|
self.dot_file += f"label=\"{block['label']}\"\n"
|
|
self.dot_file += f"labeljust=l\n"
|
|
for node in block["texts"]:
|
|
self.dot_file += f"{node}\n"
|
|
self.dot_file += "}\n\n"
|
|
|
|
#for layer in self.layers.keys():
|
|
# self.dot_file += f"layer{layer} [style=invis]\n"
|
|
|
|
#ranking = " -- ".join([f"layer{layer}" for layer in self.layers.keys()])
|
|
#self.dot_file += f"{ranking} [style=invis]\n"
|
|
|
|
for link in self.links:
|
|
if self.links[link]["to"] != "":
|
|
self.dot_file += f"{self.links[link]['from']} -- {self.links[link]['to']}"
|
|
if self.links[link]["head"] != "":
|
|
self.dot_file += f" [lhead=cluster_{self.links[link]['head']}]"
|
|
self.dot_file += "\n"
|
|
|
|
#for layer, nodes in self.layers.items():
|
|
# self.dot_file += "{rank=same; "
|
|
# self.dot_file += "layer{layer}; "
|
|
# for node in nodes:
|
|
# self.dot_file += f"{node}; "
|
|
# self.dot_file += "}\n"
|
|
|
|
self.dot_file += FOOTER
|
|
|
|
def make_dot(self, format="svg", dot_file="dot.gv", svg_file="graph.svg"):
|
|
if self.dot_file != "":
|
|
with open(dot_file, "w") as f:
|
|
f.write(self.dot_file)
|
|
if format == "svg":
|
|
os.system(f"dot -T{format} {dot_file} -o {svg_file}")
|
|
|
|
|
|
|