1
1
package org .tensortapestry .loom .graph .export .graphviz ;
2
2
3
+ import java .awt .*;
3
4
import java .util .*;
5
+ import java .util .List ;
6
+
4
7
import org .tensortapestry .graphviz .*;
5
8
import org .tensortapestry .loom .graph .LoomNode ;
6
9
import org .tensortapestry .loom .graph .dialects .tensorops .*;
@@ -13,19 +16,27 @@ public void exportNode(
13
16
GraphVisualizer .ExportContext context ,
14
17
LoomNode appNode
15
18
) {
19
+ DotGraph dotGraph = context .getDotGraph ();
16
20
var application = ApplicationNode .wrap (appNode );
17
21
var operation = application .getOperationNode ();
18
22
19
- var operationColor = context . colorSchemeForNode (operation .getId ()). getKey ( );
23
+ var opCluster = dotGraph . assertLookup (operation .getId () + "_op_cluster" , DotGraph . Cluster . class );
20
24
21
- DotGraph dotGraph = context .getDotGraph ();
22
- var dotCluster = dotGraph .createCluster ("app_%s" .formatted (appNode .getId ()));
25
+ Color operationColor = context .colorSchemeForNode (operation .getId ()).getKey ();
26
+
27
+ var clusterColor = "%s:%s" .formatted (
28
+ FormatUtils .colorToRgbaString (operationColor .brighter ()),
29
+ FormatUtils .colorToRgbaString (operationColor ));
30
+
31
+ var dotCluster = opCluster .createCluster ("app_%s" .formatted (appNode .getId ()));
23
32
dotCluster
24
33
.getAttributes ()
25
34
.set (GraphvizAttribute .NODESEP , 0.2 )
26
35
.set (GraphvizAttribute .RANKSEP , 0.2 )
27
- .set (GraphvizAttribute .FILLCOLOR , operationColor .brighter ())
28
- .set (GraphvizAttribute .STYLE , "filled, dashed, rounded" );
36
+ .set (GraphvizAttribute .PENWIDTH , 2 )
37
+ .set (GraphvizAttribute .BGCOLOR , clusterColor )
38
+ .set (GraphvizAttribute .GRADIENTANGLE , 315 )
39
+ .set (GraphvizAttribute .STYLE , "filled, dashed, bold, rounded" );
29
40
30
41
var dotOpNode = dotGraph .assertLookup (operation .getId ().toString (), DotGraph .Node .class );
31
42
@@ -55,8 +66,10 @@ public void exportNode(
55
66
56
67
dotNode .set (GraphvizAttribute .LABEL , HtmlLabel .from (labelTable ));
57
68
58
- selectionMapNodes (context , dotCluster , application , dotNode , application .getInputs (), true );
59
- selectionMapNodes (context , dotCluster , application , dotNode , application .getOutputs (), false );
69
+ var useRouteNodes = operation .getApplicationNodes ().stream ().count () > 1 ;
70
+
71
+ selectionMapNodes (context , dotCluster , application , dotNode , application .getInputs (), useRouteNodes , true );
72
+ selectionMapNodes (context , dotCluster , application , dotNode , application .getOutputs (), useRouteNodes , false );
60
73
}
61
74
62
75
protected static void selectionMapNodes (
@@ -65,6 +78,7 @@ protected static void selectionMapNodes(
65
78
ApplicationNode application ,
66
79
DotGraph .Node dotNode ,
67
80
Map <String , List <TensorSelection >> inputs ,
81
+ boolean useRouteNodes ,
68
82
boolean isInput
69
83
) {
70
84
var dotGraph = context .getDotGraph ();
@@ -76,6 +90,7 @@ protected static void selectionMapNodes(
76
90
77
91
selCluster
78
92
.getAttributes ()
93
+ .set (GraphvizAttribute .STYLE , "invis" )
79
94
.set (GraphvizAttribute .PERIPHERIES , 0 )
80
95
.set (GraphvizAttribute .RANK , "same" );
81
96
@@ -120,22 +135,44 @@ protected static void selectionMapNodes(
120
135
)
121
136
);
122
137
123
- var routeId = "%s_route_%s_%s" .formatted (application .getOperationId (), ioDesc , tensorId );
124
- var routeNode = context .getDotGraph ().assertLookup (routeId , DotGraph .Node .class );
138
+ DotGraph .Node sourceNode ;
139
+ if (useRouteNodes ) {
140
+ var routeId = "%s_route_%s_%s" .formatted (application .getOperationId (), ioDesc , tensorId );
141
+ sourceNode = context .getDotGraph ().assertLookup (routeId , DotGraph .Node .class );
142
+ } else {
143
+ sourceNode = context .getDotGraph ().assertLookup (tensorId .toString (), DotGraph .Node .class );
144
+ }
125
145
126
146
DotGraph .Edge routeEdge ;
127
147
DotGraph .Edge selEdge ;
128
148
129
149
if (isInput ) {
130
- routeEdge = dotGraph .createEdge (routeNode , dotSelectionNode );
150
+ routeEdge = dotGraph .createEdge (sourceNode , dotSelectionNode );
131
151
selEdge = dotCluster .createEdge (dotSelectionNode , dotNode );
152
+
153
+ if (useRouteNodes ) {
154
+ routeEdge .set (GraphvizAttribute .TAILCLIP , false );
155
+ }
156
+
132
157
} else {
133
158
selEdge = dotCluster .createEdge (dotNode , dotSelectionNode );
134
- routeEdge = dotGraph .createEdge (dotSelectionNode , routeNode );
159
+ routeEdge = dotGraph .createEdge (dotSelectionNode , sourceNode );
160
+
161
+ if (useRouteNodes ) {
162
+ routeEdge .set (GraphvizAttribute .HEADCLIP , false );
163
+ }
135
164
}
136
165
166
+ selEdge
167
+ .set (GraphvizAttribute .COLOR , tensorColor )
168
+ .set (GraphvizAttribute .ARROWHEAD , "none" );
169
+ routeEdge
170
+ .set (GraphvizAttribute .COLOR , tensorColor + "C0" )
171
+ .set (GraphvizAttribute .ARROWHEAD , "none" );
172
+
137
173
for (var e : List .of (routeEdge , selEdge )) {
138
- e .set (GraphvizAttribute .COLOR , tensorColor ).set (GraphvizAttribute .PENWIDTH , 12 );
174
+ e
175
+ .set (GraphvizAttribute .PENWIDTH , 24 );
139
176
}
140
177
141
178
// Force the selection nodes to cluster and layout in call order.
0 commit comments