44try :
55 import dash
66 import dash_cytoscape as cyto
7- from dash import html , Output , Input
7+ from dash import Input , Output , html
88except ImportError :
99 raise ImportError ("Please install the 'dash' and 'dash-cytoscape' packages to use the visualizer." )
1010
11+ import json
1112import os
1213import sys
13- import json
1414
1515
1616def main ():
@@ -32,32 +32,28 @@ def main():
3232
3333 # Create nodes for observable registers.
3434 for register in range (graph ["observable_registers" ]):
35- elements .append ({
36- "data" : {
37- "id" : f"obs_register_{ register } " ,
38- "label" : f"Observable register { register } " ,
39- "info" : "This is an observable register. It's an output of a workflow."
40- },
41- "classes" : "register"
42- })
35+ elements .append (
36+ {
37+ "data" : {
38+ "id" : f"obs_register_{ register } " ,
39+ "label" : f"Observable register { register } " ,
40+ "info" : "This is an observable register. It's an output of a workflow." ,
41+ },
42+ "classes" : "register" ,
43+ }
44+ )
4345 ins [register ] = [f"obs_register_{ register } " ]
4446 rendered_registers .add (register )
4547
46-
4748 script_i = 0
4849 execution_i = 0
4950 # First pass to create nodes and mark input registers.
5051 for task in graph ["tasks" ]:
5152 if task ["type" ] == "script" :
5253 id = f"script_{ script_i } "
53- elements .append ({
54- "data" : {
55- "id" : id ,
56- "label" : task .get ("name" , f"Script { script_i } " ),
57- "info" : task
58- },
59- "classes" : "script"
60- })
54+ elements .append (
55+ {"data" : {"id" : id , "label" : task .get ("name" , f"Script { script_i } " ), "info" : task }, "classes" : "script" }
56+ )
6157 if task ["reactive" ]:
6258 elements [- 1 ]["classes" ] += " reactive"
6359 script_i += 1
@@ -67,14 +63,12 @@ def main():
6763 ins [register ].append (id )
6864 elif task ["type" ] == "execution" :
6965 id = f"execution_{ execution_i } "
70- elements .append ({
71- "data" : {
72- "id" : id ,
73- "label" : task .get ("name" , f"Execution { execution_i } " ),
74- "info" : task
75- },
76- "classes" : "execution"
77- })
66+ elements .append (
67+ {
68+ "data" : {"id" : id , "label" : task .get ("name" , f"Execution { execution_i } " ), "info" : task },
69+ "classes" : "execution" ,
70+ }
71+ )
7872 if task ["exclusive" ]:
7973 elements [- 1 ]["classes" ] += " exclusive"
8074
@@ -99,31 +93,37 @@ def main():
9993
10094 for register in registers :
10195 if register not in ins :
102- elements .append ({
103- "data" : {
104- "id" : f"register_{ register } " ,
105- "label" : f"Register { register } " ,
106- "info" : f"This is a register. It's an intermediate value in a workflow."
107- },
108- "classes" : "register"
109- })
96+ elements .append (
97+ {
98+ "data" : {
99+ "id" : f"register_{ register } " ,
100+ "label" : f"Register { register } " ,
101+ "info" : f"This is a register. It's an intermediate value in a workflow." ,
102+ },
103+ "classes" : "register" ,
104+ }
105+ )
110106 ins [register ] = [f"register_{ register } " ]
111107 rendered_registers .add (register )
112108 for id in ins [register ]:
113109 if task ["type" ] == "script" :
114- elements .append ({
115- "data" : {
116- "source" : f"script_{ script_i } " ,
117- "target" : id ,
110+ elements .append (
111+ {
112+ "data" : {
113+ "source" : f"script_{ script_i } " ,
114+ "target" : id ,
115+ }
118116 }
119- } )
117+ )
120118 elif task ["type" ] == "execution" :
121- elements .append ({
122- "data" : {
123- "source" : f"execution_{ execution_i } " ,
124- "target" : id ,
119+ elements .append (
120+ {
121+ "data" : {
122+ "source" : f"execution_{ execution_i } " ,
123+ "target" : id ,
124+ }
125125 }
126- } )
126+ )
127127 if register not in rendered_registers :
128128 elements [- 1 ]["data" ]["label" ] = f"via register { register } "
129129
@@ -133,70 +133,99 @@ def main():
133133 execution_i += 1
134134
135135 app = dash .Dash (__name__ )
136- app .layout = html .Div ([
137- html .Div ([
138- cyto .Cytoscape (
139- id = 'cytoscape' ,
140- layout = {"name" : "breadthfirst" , "directed" : True },
141- style = {'width' : '100%' , 'height' : '100vh' },
142- elements = elements ,
143- stylesheet = [
144- {"selector" : "node" , "style" : {
145- "label" : "data(label)" ,
146- "text-valign" : "center" ,
147- "text-margin-y" : "-20px" ,
148- }},
149- {"selector" : "edge" , "style" : {
150- "curve-style" : "bezier" , # Makes edges curved for better readability
151- "target-arrow-shape" : "triangle" , # Adds an arrowhead to indicate direction
152- "arrow-scale" : 1.5 , # Makes the arrow larger
153- "line-color" : "#0074D9" , # Edge color
154- "target-arrow-color" : "#0074D9" , # Arrow color
155- "width" : 2 , # Line thickness
156- "content" : "data(label)" , # Show edge label on hover
157- "font-size" : "12px" ,
158- "color" : "#ff4136" ,
159- "text-background-opacity" : 1 ,
160- "text-background-color" : "white" ,
161- "text-background-shape" : "roundrectangle" ,
162- "text-border-opacity" : 1 ,
163- "text-border-width" : 1 ,
164- "text-border-color" : "#ff4136" ,
165- }},
166- {"selector" : ".register" , "style" : {
167- "shape" : "rectangle" ,
168- }},
169- {"selector" : ".script" , "style" : {
170- "shape" : "roundrectangle" ,
171- }},
172- {"selector" : ".execution" , "style" : {
173- "shape" : "ellipse" ,
174- }},
175- {"selector" : ".reactive" , "style" : {
176- "background-color" : "#ff851b" ,
177- }},
178- {"selector" : ".exclusive" , "style" : {
179- "background-color" : "#ff4136" ,
180- }},
136+ app .layout = html .Div (
137+ [
138+ html .Div (
139+ [
140+ cyto .Cytoscape (
141+ id = "cytoscape" ,
142+ layout = {"name" : "breadthfirst" , "directed" : True },
143+ style = {"width" : "100%" , "height" : "100vh" },
144+ elements = elements ,
145+ stylesheet = [
146+ {
147+ "selector" : "node" ,
148+ "style" : {
149+ "label" : "data(label)" ,
150+ "text-valign" : "center" ,
151+ "text-margin-y" : "-20px" ,
152+ },
153+ },
154+ {
155+ "selector" : "edge" ,
156+ "style" : {
157+ "curve-style" : "bezier" , # Makes edges curved for better readability
158+ "target-arrow-shape" : "triangle" , # Adds an arrowhead to indicate direction
159+ "arrow-scale" : 1.5 , # Makes the arrow larger
160+ "line-color" : "#0074D9" , # Edge color
161+ "target-arrow-color" : "#0074D9" , # Arrow color
162+ "width" : 2 , # Line thickness
163+ "content" : "data(label)" , # Show edge label on hover
164+ "font-size" : "12px" ,
165+ "color" : "#ff4136" ,
166+ "text-background-opacity" : 1 ,
167+ "text-background-color" : "white" ,
168+ "text-background-shape" : "roundrectangle" ,
169+ "text-border-opacity" : 1 ,
170+ "text-border-width" : 1 ,
171+ "text-border-color" : "#ff4136" ,
172+ },
173+ },
174+ {
175+ "selector" : ".register" ,
176+ "style" : {
177+ "shape" : "rectangle" ,
178+ },
179+ },
180+ {
181+ "selector" : ".script" ,
182+ "style" : {
183+ "shape" : "roundrectangle" ,
184+ },
185+ },
186+ {
187+ "selector" : ".execution" ,
188+ "style" : {
189+ "shape" : "ellipse" ,
190+ },
191+ },
192+ {
193+ "selector" : ".reactive" ,
194+ "style" : {
195+ "background-color" : "#ff851b" ,
196+ },
197+ },
198+ {
199+ "selector" : ".exclusive" ,
200+ "style" : {
201+ "background-color" : "#ff4136" ,
202+ },
203+ },
204+ ],
205+ ),
181206 ],
207+ style = {"flex" : "3" , "height" : "100vh" },
182208 ),
183- ], style = {"flex" : "3" , "height" : "100vh" }),
184-
185- html .Div ([
186- html .Pre (id = 'node-data' , style = {
187- "padding" : "10px" ,
188- "white-space" : "pre" ,
189- "overflow" : "auto" ,
190- "max-height" : "95vh" ,
191- "max-width" : "100%"
192- })
193- ], style = {"flex" : "1" , "height" : "100vh" , "background-color" : "#f7f7f7" })
194- ], style = {"display" : "flex" , "flex-direction" : "row" , "height" : "100vh" })
195-
196- @app .callback (
197- Output ('node-data' , 'children' ),
198- Input ('cytoscape' , 'tapNodeData' )
209+ html .Div (
210+ [
211+ html .Pre (
212+ id = "node-data" ,
213+ style = {
214+ "padding" : "10px" ,
215+ "white-space" : "pre" ,
216+ "overflow" : "auto" ,
217+ "max-height" : "95vh" ,
218+ "max-width" : "100%" ,
219+ },
220+ )
221+ ],
222+ style = {"flex" : "1" , "height" : "100vh" , "background-color" : "#f7f7f7" },
223+ ),
224+ ],
225+ style = {"display" : "flex" , "flex-direction" : "row" , "height" : "100vh" },
199226 )
227+
228+ @app .callback (Output ("node-data" , "children" ), Input ("cytoscape" , "tapNodeData" ))
200229 def display_task_info (data ):
201230 if data is None :
202231 return "Click on a node to see its info."
0 commit comments