1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
########################################################################################
# #
# Author: Herve Menager, #
# Organization:'Biological Software and Databases' Group, Institut Pasteur, Paris. #
# Distributed under GPLv2 Licence. Please refer to the COPYING.LIB document. #
# #
########################################################################################
import pygraphviz as pgv #@UnresolvedImport
from logging import getLogger#@UnresolvedImport
log = getLogger(__name__)
from copy import deepcopy
def layout(workflow, program='dot', format='svg'):
workflow = deepcopy(workflow) # we are working on a copy of the original workflow object to be able to tweak the IDs safely
g=pgv.AGraph(strict=False,directed=True)
g.graph_attr['label']=workflow.title
g.graph_attr['rankdir']='LR'
g.graph_attr['tooltip']=workflow.title
g.graph_attr['fontname']='Helvetica'
g.node_attr['fontname']='Helvetica'
g.edge_attr['fontname']='Helvetica'
links = workflow.links
parameters = workflow.parameters
# this part
# - removes workflow parameters which are not used in two different task inputs
# - renames the corresponding task parameters to the prompt of the source workflow parameter
for link in workflow.links:
keep_flag = (link.from_task is not None and link.to_task is not None)\
or\
(link.to_task and len([l for l in workflow.links if not(l.from_task) \
and l.from_parameter==link.from_parameter ])>1)
if not keep_flag:
links.remove(link)
if (link.from_parameter and not link.from_task):
p = [param for param in workflow.parameters if link.from_parameter==param.id][0]
link.to_parameter=p.prompt.replace('\n','').strip()
parameters.remove(p)
if link.to_parameter and not link.to_task:
p = [param for param in workflow.parameters if link.to_parameter==param.id][0]
link.from_parameter=p.prompt.replace('\n','').strip()
parameters.remove(p)
for task in workflow.tasks:
#inputs = '|'.join(list(set(['<%s>%s' % (link.to_parameter,link.to_parameter) for link in workflow.links if link.to_task==task.id])))
#outputs = '|'.join(list(set(['<%s>%s' % (link.from_parameter,link.from_parameter) for link in workflow.links if link.from_task==task.id])))
#label = "%(service)s|{{%(inputs)s}|%(description)s|{%(outputs)s}}" % {'service':task.service, 'description':task.description.replace('\n','').strip(), 'inputs':inputs,'outputs':outputs}
#g.add_node(task,label=label,shape='record',tooltip=task.description)
d = task.description.replace('\n','').strip()
s = task.service.replace('\n','').strip()
if d is not None and d!='':
label = '%s (%s)' % (d,s)
else:
label = '%s' % s
g.add_node(task,label=label,shape='box',tooltip=task.description)
for param in parameters:
g.add_node(param, label=param.prompt.replace('\n','').strip(), shape='oval')
for link in links:
# sp, tp = None, None
if link.from_task:
s = [s for s in workflow.tasks if s.id==link.from_task][0]
# sp = link.from_parameter
else:
s = [s for s in workflow.parameters if s.id==link.from_parameter][0]
if link.to_task:
t = [t for t in workflow.tasks if t.id==link.to_task][0]
# tp = link.to_parameter
else:
t = [t for t in workflow.parameters if t.id==link.to_parameter][0]
# if sp and tp:
# g.add_edge(g.get_node(s),g.get_node(t), headport=tp, tailport=sp)
# elif sp:
# g.add_edge(g.get_node(s),g.get_node(t), tailport=sp)
# elif tp:
# g.add_edge(g.get_node(s),g.get_node(t), headport=tp)
# else:
# g.add_edge(g.get_node(s),g.get_node(t))
if not(g.has_edge(g.get_node(s),g.get_node(t))):
g.add_edge(g.get_node(s),g.get_node(t))
#log.error(g.to_string())
g.layout(prog=program)
#log.error(g.to_string())
#log.error(g.draw(format=format))
return g.draw(format=format)
|