comparison env/lib/python3.9/site-packages/gxformat2/cytoscape.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000 (2021-03-22)
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """Build standalone visualization for Galaxy workflows."""
2 import argparse
3 import json
4 import os
5 import string
6 import sys
7
8 import pkg_resources
9
10 from gxformat2.model import ensure_step_position
11 from gxformat2.normalize import steps_normalized
12
13 CYTOSCAPE_JS_TEMPLATE = pkg_resources.resource_filename(__name__, 'cytoscape.html')
14 MAIN_TS_PREFIX = "toolshed.g2.bx.psu.edu/repos/"
15 SCRIPT_DESCRIPTION = """
16 This script converts the an executable Galaxy workflow (in either format -
17 Format 2 or native .ga) into a format for visualization with Cytoscape
18 (https://cytoscape.org/).
19
20 If the target output path ends with .html this script will output a HTML
21 page with the workflow visualized using cytoscape.js. Otherwise, this script
22 will output a JSON description of the workflow elements for consumption by
23 Cytoscape.
24 """
25
26
27 def to_cytoscape(workflow_path: str, output_path=None):
28 """Produce cytoscape output for supplied workflow path."""
29 if output_path is None:
30 output_path, _ = os.path.splitext(workflow_path)
31 output_path += ".html"
32
33 steps = steps_normalized(workflow_path=workflow_path)
34 elements = []
35 for i, step in enumerate(steps):
36 step_id = step.get("id") or step.get("label") or str(i)
37 step_type = step.get("type") or 'tool'
38 classes = ["type_%s" % step_type]
39 if step_type in ['tool', 'subworkflow']:
40 classes.append("runnable")
41 else:
42 classes.append("input")
43
44 tool_id = step.get("tool_id")
45 if tool_id and tool_id.startswith(MAIN_TS_PREFIX):
46 tool_id = tool_id[len(MAIN_TS_PREFIX):]
47 label = step.get("id") or step.get("label") or ("tool:%s" % tool_id) or str(i)
48 ensure_step_position(step, i)
49 node_position = dict(x=int(step["position"]["left"]), y=int(step["position"]["top"]))
50 repo_link = None
51 if "tool_shed_repository" in step:
52 repo = step["tool_shed_repository"]
53 repo_link = "https://" + repo["tool_shed"] + "/view/" + repo["owner"] + "/" + repo["name"] + "/" + repo["changeset_revision"]
54 node_data = {
55 "id": step_id,
56 "label": label,
57 "doc": step.get("doc"),
58 "tool_id": step.get("tool_id"),
59 "step_type": step_type,
60 "repo_link": repo_link
61 }
62 elements.append({"group": "nodes", "data": node_data, "classes": classes, "position": node_position})
63 for key, value in (step.get("in") or {}).items():
64 # handle lists?
65 if isinstance(value, dict) and 'source' in value:
66 value = value["source"]
67 elif isinstance(value, dict):
68 continue
69 if "/" in value:
70 from_step, output = value.split("/", 1)
71 else:
72 from_step, output = value, None
73 edge_id = "%s__to__%s" % (step_id, from_step)
74 edge_data = {"id": edge_id, "source": from_step, "target": step_id, "input": key, "output": output}
75 elements.append({"group": "edges", "data": edge_data})
76
77 if output_path.endswith(".html"):
78 with open(CYTOSCAPE_JS_TEMPLATE, "r") as f:
79 template = f.read()
80 viz = string.Template(template).safe_substitute(elements=json.dumps(elements))
81 with open(output_path, "w") as f:
82 f.write(viz)
83 else:
84 with open(output_path, "w") as f:
85 json.dump(elements, f)
86
87
88 def main(argv=None):
89 """Entry point for building Cytoscape visualizations of Galaxy workflows."""
90 if argv is None:
91 argv = sys.argv[1:]
92
93 args = _parser().parse_args(argv)
94
95 workflow_path = args.input_path
96 output_path = args.output_path
97 to_cytoscape(workflow_path, output_path)
98
99
100 def _parser():
101 parser = argparse.ArgumentParser(description=SCRIPT_DESCRIPTION)
102 parser.add_argument('input_path', metavar='INPUT', type=str,
103 help='input workflow path (.ga/gxwf.yml)')
104 parser.add_argument('output_path', metavar='OUTPUT', type=str, nargs="?",
105 help='output viz path (.json/.html)')
106 return parser
107
108
109 if __name__ == "__main__":
110 main()