I want to create a graph with both splines=line
and splines=splines
, similar to the image below.
However, to achieve this, I had to create two separate graphs via the R
package DiagrammeR
and combine them using the figpatch
and patchwork
packages.
Is this possible just with graphviz
? I'm not 100% certain, but I don't think it is… But just want to cover all bases to make sure.
Can someone please confirm / deny my hunch. If the latter, some examples or resources on how to do so would be greatly appreciated.
Please let me know if you need more info about my questions.
Below is the code used to generate the graphs.
Graph 1: The one on the left.
digraph dot {
// splines = curved;
node[fontname = arial, width=1.5, height=1.5, shape=circle, fontsize=50, style = filled, penwidth = 3];
edge[fontname = arial, penwidth = 3.6, fontsize = 50]
RItb0 [pos = "000,0", style = invis, fillcolor = palevioletred];
RIpb0 [pos = "100,0", style = invis, fillcolor = darkseagreen3];
RIsi0 [pos = "200,0", style = invis, fillcolor = white];
RIbhs0 [pos = "300,0", style = invis, fillcolor = mediumorchid3];
RIdep0 [pos = "400,0", style = invis, fillcolor = cadetblue3];
RItb [pos = "000,100", width = 3, height = 3, fillcolor = palevioletred];
RIpb [pos = "100,100", width = 3, height = 3, fillcolor = darkseagreen3];
RIsi [pos = "200,100", width = 3, height = 3, fillcolor = white];
RIbhs [pos = "300,100", width = 3, height = 3, fillcolor = mediumorchid3];
RIdep [pos = "400,100", width = 3, height = 3, fillcolor = cadetblue3];
tb1 [pos = "000,200", style = invis, fillcolor = palevioletred];
pb1 [pos = "100,200", style = invis, fillcolor = darkseagreen3];
si1 [pos = "200,200", style = invis, fillcolor = white];
bhs1 [pos = "300,200", style = invis, fillcolor = mediumorchid3];
dep1 [pos = "400,200", style = invis, fillcolor = cadetblue3];
{ edge [weight = 10, minlen = 4.0; style = invis, penwidth = 3];
// Random Intercepts
RItb0 -> RIpb0 ; // [minlen = 4.0];
RIpb0 -> RIsi0 ; // [minlen = 4.0];
RIsi0 -> RIbhs0 ; // [minlen = 4.0];
RIbhs0 -> RIdep0 ; // [minlen = 4.0];
RItb -> RIpb ; // [minlen = 4.0];
RIpb -> RIsi ; // [minlen = 4.0];
RIsi -> RIbhs ; // [minlen = 4.0];
RIbhs -> RIdep ; // [minlen = 4.0];
tb1 -> pb1 ;
pb1 -> si1 ;
si1 -> bhs1 ;
bhs1 -> dep1 ;
}
// autogregrssive paths
{ rank = same; RItb0 -> RItb [style = invis, labeldistance = 4.3, minlen = 6, color = palevioletred, style = invis]; }
{ rank = same; RItb -> tb1 [style = invis, labeldistance = 4.3, minlen = 6, color = palevioletred, style = invis]; }
{ rank = same; RIpb0 -> RIpb [style = invis, labeldistance = 4.3, minlen = 6, color = darkseagreen3, headlabel = ".28"]; }
{ rank = same; RIpb -> pb1 [style = invis, labeldistance = 4.3, minlen = 6, color = darkseagreen3, headlabel = ".28"]; }
{ rank = same; RIsi0 -> RIsi [style = invis, labelangle = 29.0, labeldistance = 4.3, minlen = 6, headlabel = ".35"]; }
{ rank = same; RIsi -> si1 [style = invis, labelangle = 29.0, labeldistance = 4.3, minlen = 6, headlabel = ".35"]; }
{ rank = same; RIbhs0 -> RIbhs [style = invis, labelangle = 29.0, labeldistance = 4.3, minlen = 6, color = mediumorchid3, headlabel = ".43"];}
{ rank = same; RIbhs -> bhs1 [style = invis, labelangle = 29.0, labeldistance = 4.3, minlen = 6, color = mediumorchid3, headlabel = ".43"];}
{ rank = same; RIdep0 -> RIdep [style = invis, labelangle = 29.0, labeldistance = 4.3, minlen = 6, color = cadetblue3; style = invis]; }
{ rank = same; RIdep -> dep1 [style = invis, labelangle = 29.0, labeldistance = 4.3, minlen = 6, color = cadetblue3; style = invis]; }
{
// cross-lagged paths
edge[style = dashed, labeldistance = 4.3, labelfloat = false, constraint = true, minlen = 5]
RIpb -> RItb [penwidth = 5, dir = both, label = ".47"];
RIpb -> RIbhs [penwidth = 5, dir = both, label = ".55"];
RIpb -> RIdep [penwidth = 5, dir = both, label = ".67"];
RItb -> RIbhs [penwidth = 5, dir = both, label = ".60"];
RItb -> RIdep [penwidth = 5, dir = both, label = ".58"];
RItb -> RIsi [penwidth = 9.5, dir = both, style = dashed, label = ".27"];
RIbhs -> RIsi [penwidth = 9.5, dir = both, style = dashed, label = ".31"];
RIdep -> RIsi [penwidth = 9.5, dir = both, style = dashed, label = ".37"];
RIbhs -> RIdep [penwidth = 5, dir = both, label = ".62"];
}
}
Graph 2: The one on the right.
digraph dot {
splines = line;
node[fontname = arial, width=1.5, height=1.5, shape=circle, fontsize=36, style = filled, penwidth = 3];
edge[fontname = arial, penwidth = 3.6, fontsize = 28]
tb1 [pos = "000,200", fillcolor = palevioletred];
pb1 [pos = "100,200", fillcolor = darkseagreen3];
si1 [pos = "200,200", fillcolor = white];
bhs1 [pos = "300,200", fillcolor = mediumorchid3];
dep1 [pos = "400,200", fillcolor = cadetblue3];
tb2 [pos = "000,300", fillcolor = palevioletred];
pb2 [pos = "100,300", fillcolor = darkseagreen3];
si2 [pos = "200,300", fillcolor = white];
bhs2 [pos = "300,300", fillcolor = mediumorchid3];
dep2 [pos = "400,300", fillcolor = cadetblue3];
tb3 [pos = "000,400", fillcolor = palevioletred];
pb3 [pos = "100,400", fillcolor = darkseagreen3];
si3 [pos = "200,400", fillcolor = white];
bhs3 [pos = "300,400", fillcolor = mediumorchid3];
dep3 [pos = "400,400", fillcolor = cadetblue3];
tb4 [pos = "000,500", fillcolor = palevioletred];
pb4 [pos = "100,500", fillcolor = darkseagreen3];
si4 [pos = "200,500", fillcolor = white];
bhs4 [pos = "300,500", fillcolor = mediumorchid3];
dep4 [pos = "400,500", fillcolor = cadetblue3];
tb5 [pos = "000,600", fillcolor = palevioletred];
pb5 [pos = "100,600", fillcolor = darkseagreen3];
si5 [pos = "200,600", fillcolor = white];
bhs5 [pos = "300,600", fillcolor = mediumorchid3];
dep5 [pos = "400,600", fillcolor = cadetblue3];
{ edge [weight = 10, minlen = 4.0; style = invis, penwidth = 3];
tb1 -> pb1 ;
pb1 -> si1 ;
si1 -> bhs1 ;
bhs1 -> dep1 ;
tb2 -> pb2 ;
pb2 -> si2 ;
si2 -> bhs2 ;
bhs2 -> dep2 ;
tb3 -> pb3 ;
pb3 -> si3 ;
si3 -> bhs3 ;
bhs3 -> dep3 ;
tb4 -> pb4 ;
pb4 -> si4 ;
si4 -> bhs4 ;
bhs4 -> dep4 ;
tb5 -> pb5 ;
pb5 -> si5 ;
si5 -> bhs5 ;
bhs5 -> dep5 ;
}
// autogregrssive paths
{ rank = same; tb1 -> tb2 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = palevioletred, style = invis]; }
{ rank = same; tb2 -> tb3 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = palevioletred, headlabel = ".37"]; }
{ rank = same; tb3 -> tb4 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = palevioletred, headlabel = ".28"]; }
{ rank = same; tb4 -> tb5 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = palevioletred, headlabel = ".30"]; }
{ rank = same; pb1 -> pb2 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = darkseagreen3, headlabel = ".28"]; }
{ rank = same; pb2 -> pb3 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = darkseagreen3; style = invis]; }
{ rank = same; pb3 -> pb4 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = darkseagreen3, headlabel = ".30"]; }
{ rank = same; pb4 -> pb5 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = darkseagreen3, headlabel = ".45"]; }
{ rank = same; si1 -> si2 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, style = bold, headlabel = ".35"]; }
{ rank = same; si2 -> si3 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, style = bold, headlabel = ".25"]; }
{ rank = same; si3 -> si4 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, style = bold; style = invis]; }
{ rank = same; si4 -> si5 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, style = bold, headlabel = ".27"]; }
{ rank = same; bhs1 -> bhs2 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = mediumorchid3, headlabel = ".43"];}
{ rank = same; bhs2 -> bhs3 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = mediumorchid3, headlabel = ".49"]; }
{ rank = same; bhs3 -> bhs4 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = mediumorchid3, headlabel = ".50"]; }
{ rank = same; bhs4 -> bhs5 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = mediumorchid3, headlabel = ".48"]; }
{ rank = same; dep1 -> dep2 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = cadetblue3; style = invis]; }
{ rank = same; dep2 -> dep3 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = cadetblue3, headlabel = ".25"]; }
{ rank = same; dep3 -> dep4 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = cadetblue3, headlabel = ".27"]; }
{ rank = same; dep4 -> dep5 [labelangle = -39.5, labeldistance = 3.6, minlen = 16, color = cadetblue3, headlabel = ".37"]; }
{
// cross-lagged paths
edge[style = dashed, labelangle = -39.5, labeldistance = 3.6, labelfloat = true]
## [headlabel=<<table border="0" cellborder="0"><tr><td bgcolor="white">Head Label</td></tr></table>>,taillabel="Tail Label"]
bhs1 -> pb2 [labelangle = 39.5, color = mediumorchid3, headlabel = ".39"];
bhs2 -> pb3 [labelangle = 39.5, color = mediumorchid3, headlabel = ".25"];
bhs3 -> pb4 [labelangle = 39.5, color = mediumorchid3, headlabel = ".31"];
bhs3 -> si4 [color = mediumorchid3, headlabel = ".30"];
bhs4 -> tb5 [color = mediumorchid3, headlabel = ".25"];
dep4 -> pb5 [labelangle = 39.5, color = cadetblue3, headlabel = ".26"];
pb2 -> tb3 [color = darkseagreen3, headlabel = ".25"];
pb3 -> si4 [color = darkseagreen3, headlabel = ".30"];
pb3 -> dep4 [color = darkseagreen3, headlabel = ".35"];
pb3 -> bhs4 [color = darkseagreen3, headlabel = ".28"];
pb4 -> dep5 [color = darkseagreen3, headlabel = ".30"];
pb4 -> bhs5 [color = darkseagreen3, headlabel = ".27"];
si1 -> bhs2 [headlabel = ".19"];
si1 -> dep2 [headlabel = ".17"];
si1 -> pb2 [headlabel = ".14"];
si2 -> pb3 [headlabel = ".16"];
tb2 -> si3 [color = palevioletred, headlabel = ".15"];
}
}
No - the splines attribute applies to the entire graph, so it can't be done with a single invocation / pass of a Graphviz tool
Yes - Chop your graph into multiple graphs, each cluster into its own graph. Each (new) graph can have a different splines value. Run each (new) graph through dot -Tdot
to determine layouts of each separately. Run those results through gvpack (https://www.graphviz.org/pdf/gvpack.1.pdf 2) to combine them into a single graph. And finally hand that to neato -n2
(https://graphviz.org/faq/#FaqDotWithNodeCoords) to produce an output file.
Like so:
S="";
for f in sub[12].gv; # sub1.gv and sub2.gv are the two created graphs
do
T=dot;
F=`basename $f .gv`;
dot -T$T $f >$F.$T;
S="$S $F.$T";
done;
gvpack -array_i3 $S |
neato -n2 -Tpng >O.png
Note - if necessary, it is possible to apply different splines values to individual edges by running a dot-formatted graph through neato -n2
multiple times, each time changing the splines value and removing individual edge pos values. Possible, but messy.