diff --git a/scripts/gen-centered-graph.py b/scripts/gen-centered-graph.py deleted file mode 100644 index ef4ff18..0000000 --- a/scripts/gen-centered-graph.py +++ /dev/null @@ -1,125 +0,0 @@ -import requests -import sys - -url = 'http://localhost:8000/notes/graph.json' -reference_node = sys.argv[1] -out = sys.argv[2] - -g = requests.get(url).json() -centered_graph = { reference_node: g[reference_node] } -del g[reference_node] -new_nodes = True - -in_emacs_tree = { - reference_node: set(), -} - -while new_nodes: - new_nodes = False - removed = set() - for k, v in g.items(): - for link in v["links"]: - if link["target"].startswith("id:"): - link["target"] = link["target"][3:] - if link['target'] in centered_graph and link.get('relation') == 'in': - centered_graph[k] = v - - for l in v["links"]: - if l.get('relation') == 'in': - t = l['target'] - if t.startswith("id:"): - t = t[3:] - - if '[' in t: - # Special case, to be handled on org_rw - continue - - if t not in in_emacs_tree: - in_emacs_tree[t] = set() - in_emacs_tree[t].add(k) - - v['links'] = [ - l for l in v["links"] - if l.get('relation') != 'in' - ] - - - removed.add(k) - new_nodes = True - break - for k in removed: - del g[k] - -in_emacs = set(centered_graph.keys()) - - -# One more round for the rest, not requiring "in" -for k, v in g.items(): - for link in v["links"]: - if link["target"].startswith("id:"): - link["target"] = link["target"][3:] - if link['target'] in in_emacs: - centered_graph[k] = v - removed.add(k) - -g = centered_graph - -f = open('graph.dot', 'wt') -f.write('digraph {\n') -# f.write('bgcolor="#222222"\n') -# f.write('fontcolor="#ffffff"\n') -f.write('maxiter=1000\n') -f.write('splines=curved\n') -# f.write('splines=spline\n') # Not supported with edges to cluster -f.write('node[shape=rect]\n') -# f.write('edge[color="#ffffff"]\n') - -def draw_subgraph(node_id): - f.write("subgraph cluster_{} {{\n".format(node_id.replace("-", "_"))) - f.write('URL="./{}.node.html"\n'.format(node_id)) - # f.write('color="#ffffff"\n') - - f.write("label=\"{}\"\n".format(g[node_id]['title'].replace("\"", "'"))) - f.write("\n") - - # print("T: {}".format(in_emacs_tree), file=sys.stderr) - for k in in_emacs_tree[node_id]: - v = g[k] - print("_" + k.replace("-", "_") + "[label=\"" + v["title"].replace("\"", "'") + "\", URL=\"" + k + ".node.html\"];", file=f) - - if k in in_emacs_tree: - draw_subgraph(k) - - f.write("\n}") - -draw_subgraph(reference_node) - -for k, v in g.items(): - if k not in in_emacs: - print("_" + k.replace("-", "_") + "[label=\"" + v["title"].replace("\"", "'") + "\", URL=\"" + k + ".node.html\"];", file=f) - -for k, v in g.items(): - for link in v["links"]: - if link["target"].startswith("id:"): - link["target"] = link["target"][3:] - - if '[' in link['target']: - # Special case, to be handled on org_rw - continue - if link['target'] not in g: - # Irrelevant - continue - if link['target'] in in_emacs_tree: - t = 'cluster_{}'.format(link['target'].replace("-", "_")) - else: - t = "_" + link["target"].replace("-", "_") - print("_" + k.replace("-", "_") + "->" + t, file=f) - -f.write('}\n') -# dot graph.dot -Tsvg graph.svg - -f.close() - -import subprocess -subprocess.call("fdp graph.dot -Tsvg -o '{}'".format(out), shell=True) -# return "graph.svg" diff --git a/scripts/gen_centered_graph.py b/scripts/gen_centered_graph.py new file mode 100644 index 0000000..8176e16 --- /dev/null +++ b/scripts/gen_centered_graph.py @@ -0,0 +1,126 @@ +import requests +import sys +import subprocess +import ops_cache +import copy +import tempfile + +# TODO: Cache results +# TODO: Properly render outgouing links + +# @ops_cache() +def gen(headline_id, graph): + reference_node = headline_id + + g = copy.deepcopy(graph) + centered_graph = { reference_node: g[reference_node] } + del g[reference_node] + new_nodes = True + + in_emacs_tree = { + reference_node: set(), + } + + while new_nodes: + new_nodes = False + removed = set() + for k, v in g.items(): + for link in v["links"]: + if link["target"].startswith("id:"): + link["target"] = link["target"][3:] + if link['target'] in centered_graph and link.get('relation') == 'in': + centered_graph[k] = v + + for l in v["links"]: + if l.get('relation') == 'in': + t = l['target'] + if t.startswith("id:"): + t = t[3:] + + if '[' in t: + # Special case, to be handled on org_rw + continue + + if t not in in_emacs_tree: + in_emacs_tree[t] = set() + in_emacs_tree[t].add(k) + + v['links'] = [ + l for l in v["links"] + if l.get('relation') != 'in' + ] + + + removed.add(k) + new_nodes = True + break + for k in removed: + del g[k] + + in_emacs = set(centered_graph.keys()) + + # One more round for the rest, not requiring "in" + for k, v in g.items(): + for link in v["links"]: + if link["target"].startswith("id:"): + link["target"] = link["target"][3:] + if link['target'] in in_emacs: + centered_graph[k] = v + removed.add(k) + + g = centered_graph + + with tempfile.NamedTemporaryFile(suffix='.dot', mode='wt') as f: + f.write('digraph {\n') + f.write('maxiter=1000\n') + f.write('splines=curved\n') + # f.write('splines=spline\n') # Not supported with edges to cluster + f.write('node[shape=rect]\n') + + def draw_subgraph(node_id): + f.write("subgraph cluster_{} {{\n".format(node_id.replace("-", "_"))) + f.write('URL="./{}.node.html"\n'.format(node_id)) + + f.write("label=\"{}\"\n".format(g[node_id]['title'].replace("\"", "'"))) + f.write("\n") + + # print("T: {}".format(in_emacs_tree), file=sys.stderr) + for k in in_emacs_tree[node_id]: + v = g[k] + print("_" + k.replace("-", "_") + "[label=\"" + v["title"].replace("\"", "'") + "\", URL=\"" + k + ".node.html\"];", file=f) + + if k in in_emacs_tree: + draw_subgraph(k) + + f.write("\n}") + + draw_subgraph(reference_node) + + for k, v in g.items(): + if k not in in_emacs: + print("_" + k.replace("-", "_") + "[label=\"" + v["title"].replace("\"", "'") + "\", URL=\"" + k + ".node.html\"];", file=f) + + for k, v in g.items(): + for link in v["links"]: + if link["target"].startswith("id:"): + link["target"] = link["target"][3:] + + if '[' in link['target']: + # Special case, to be handled on org_rw + continue + if link['target'] not in g: + # Irrelevant + continue + if link['target'] in in_emacs_tree: + t = 'cluster_{}'.format(link['target'].replace("-", "_")) + else: + t = "_" + link["target"].replace("-", "_") + print("_" + k.replace("-", "_") + "->" + t, file=f) + + f.write('}\n') + f.close() + + with tempfile.NamedTemporaryFile(suffix='.svg') as fsvg: + subprocess.call("fdp graph.dot -Tsvg -o '{}'".format(fsvg.name), shell=True) + fsvg.seek(0) + return fsvg.read().decode() diff --git a/scripts/generate.py b/scripts/generate.py index 026a960..c6ecc3d 100644 --- a/scripts/generate.py +++ b/scripts/generate.py @@ -25,6 +25,7 @@ from org_rw import token_list_to_raw import pygments import pygments.lexers import pygments.formatters +import gen_centered_graph # Set custom states for state in ("NEXT", "MEETING", "Q", "PAUSED", "SOMETIME", "TRACK", "WAITING"): @@ -710,19 +711,9 @@ def render_connections(headline_id, content, graph): # if headline_id != 'aa29be89-70e7-4465-91ed-361cf0ce62f2': # return - # TODO: Cache results - # TODO: Avoid querying graph API on script - # TODO: Properly render outgouing links logging.info("Generating centered graph for {}".format(headline_id)) - import subprocess - this_dir = os.path.dirname(os.path.abspath(__file__)) - os.makedirs('cache', exist_ok=True) - subprocess.check_call(['python3', os.path.join(this_dir, 'gen-centered-graph.py'), headline_id, 'cache/' + headline_id + '.svg']) - try: - with open('cache/' + headline_id + '.svg') as f: - content.append("
{}
".format(f.read())) - except FileNotFoundError: - logging.exception('Graph file not produced on headline: "{}"'.format(headline_id)) + svg = gen_centered_graph.gen(headline_id, graph['nodes']) + content.append("
{}
".format(svg)) def render(headline, doc, graph, headlineLevel): try: diff --git a/scripts/ops_cache.py b/scripts/ops_cache.py new file mode 100644 index 0000000..e69de29