I've reduced my problem to the following simple example:
digraph {
subgraph {rank=same; 0 -> 1 -> 2;}
0 -> 2 [label="A"];
2 -> 0 [label="B"];
}
which produces
While keeping 0, 1 and 2 in the same rank (the original example is in the context of a larger graph), I need A and B edges to be discernible. i.e. the edges to clearly match to labels and the labels to be readable.
One solution I imagined was using ports on the edge connections specified by
0:ne -> 2:nw [label="A"];
2:sw -> 0:se [label="B"];
however this produces
Other ideas? I am generating larger graphs with the same issue so a best solution would not be a completely ad-hoc manual placement of edges/labels.
Edit: A (still simplified) example of the larger generated graph is the following.
digraph {
size = "6,8.5";
ratio = "fill";
node [shape = circle];
node [fontsize = 24];
edge [fontsize = 24];
{graph [rank=same]; edge[color=invis];1;}
{graph [rank=same]; edge[color=invis];2 -> 0 -> 3 -> 4;}
0 -> 0 [label="6: 0.1764"];
0 -> 4 [label="4: 0.1304"];
0 -> 3 [label="5: 0.1551"];
0 -> 2 [label="7: 0.1489"];
0 -> 1 [label="Z: 0.3893"];
4 -> 0 [label="6: 0.1237"];
4 -> 3 [label="5: 0.05201"];
4 -> 2 [label="7: 0.15 "];
4 -> 1 [label="Z: 0.4585"];
3 -> 0 [label="6: 0.1658"];
3 -> 4 [label="4: 0.13 "];
3 -> 3 [label="5: 0.1038"];
3 -> 2 [label="7: 0.1616"];
3 -> 1 [label="Z: 0.4388"];
2 -> 0 [label="6: 0.1661"];
2 -> 4 [label="4: 0.1295"];
2 -> 3 [label="5: 0.2078"];
2 -> 2 [label="7: 0.1406"];
2 -> 1 [label="Z: 0.356 "];
1 -> 0 [label="6: 0.1103"];
1 -> 4 [label="4: 0.2591"];
1 -> 3 [label="5: 0.1382"];
1 -> 2 [label="7: 0.08581"];
1 -> 1 [label="Z: 0.1906"];
}
This produces:
which exhibits the same edge/label overlap problem in the simpler example above.
Other notes:
You can get part way there with dir="both"
and a colorList.
digraph {
subgraph {rank=same; 0 -> 1 -> 2;}
0 -> 2 [dir="both", color="black:gray", labeldistance="2", headlabel="A", taillabel="B"];
}
results in this:
I had to use labelDistance
to keep the "A" label from being drawn on top of the arrowhead. Unfortunately, I couldn't figure out how to change font color individually for the head label and tail label to make it more clear as to which label applies to which arrowhead.
The first example is clearly a bug; the edge labels should be positioned in separate locations, which would then separate the edges. (In general, we know there are holes in the flat edge code, especially dealing with labels.) One workaround is to treat some or all of the edges labels as exterior labels:
digraph {
subgraph {rank=same; 0 -> 1 -> 2;}
0 -> 2 [xlabel="A"];
2 -> 0 [xlabel="B"];
}
Concerning the issue of changing the font color for labels mentioned in the previous answer, this can be done using HTML-like labels:
0 -> 2 [dir="both", color="black:gray", labeldistance="2",
headlabel=<<font color="red">A</font>>, taillabel="B"];
This can be used for any text in place of the usual double-quoted strings.
Answers from both ssteve and emden were very useful and have been upvoted. (thank you both!)
I am incorporating input from both and answering this question in its more complex version. I still do not feel like the solution is perfect, but it is the best I can generate so far. Future answers that improve on this (see below for what seems to be still lacking) and which address the larger graph version (see question) in a way that can be automated will be accepted in lieu of this answer.
First, the best solution so far in summary: turn labels in to xlabels for some of the edges (e.g. half of all bidirectional edges, chosen randomly) and randomly color edges and corresponding labels (via fontcolor
).
In specific, here is an instantiation of this solution, where edges are randomly red, green or black:
digraph {
size = "6,10.5";
ratio = "fill";
node [shape = circle];
node [fontsize = 24];
edge [fontsize = 24];
{graph [rank=same]; edge[color=invis];1;}
{graph [rank=same]; edge[color=invis];2 -> 0 -> 3 -> 4;}
0 -> 0 [label="6: 0.1764"];
0 -> 4 [xlabel="4: 0.1304" color=blue fontcolor=blue];
0 -> 3 [xlabel="5: 0.1551" color=green fontcolor=green];
0 -> 2 [label="7: 0.1489" color=red fontcolor=red];
0 -> 1 [label="Z: 0.3893"];
4 -> 0 [xlabel="6: 0.1237" color=green fontcolor=green];
4 -> 3 [xlabel="5: 0.05201 " color=green fontcolor=green];
4 -> 2 [xlabel="7: 0.15" color=blue fontcolor=blue];
4 -> 1 [label="Z: 0.4585" color=red fontcolor=red];
3 -> 0 [xlabel="6: 0.1658"];
3 -> 4 [xlabel="4: 0.13" color=red fontcolor=red];
3 -> 3 [label="5: 0.1038" color=blue fontcolor=blue];
3 -> 2 [xlabel="7: 0.1616"];
3 -> 1 [label="Z: 0.4388"];
2 -> 0 [label="6: 0.1661" color=blue fontcolor=blue];
2 -> 4 [xlabel="4: 0.1295" color=red fontcolor=red];
2 -> 3 [label="5: 0.2078" color=green fontcolor=green];
2 -> 2 [label="7: 0.1406"];
2 -> 1 [label="Z: 0.356 "];
1 -> 0 [label="6: 0.1103" color=red fontcolor=red];
1 -> 4 [label="4: 0.2591" color=blue fontcolor=blue];
1 -> 3 [label="5: 0.1382" color=green fontcolor=green];
1 -> 2 [label="7: 0.08581 "];
1 -> 1 [label="Z: 0.1906"];
}
This produces:
This is still not completely satisfactory because:
Other things I tried:
dir="both"
+ colorlist solution. Color edges randomly. And set labeldistance
randomly between 3 and 11 for head and tail labels to avoid label overlap at nodes. Result: this is harder to automate and still results in both edge label overlap and labels which are hard to trace back to the edges they correspond to. (see below)Here's an example of the last item in the "other things I tried" solutions list above.
size = "6,8.5";
ratio = "fill";
node [shape = circle];
node [fontsize = 24];
edge [fontsize = 24];
{graph [rank=same]; edge[color=invis];1;}
{graph [rank=same]; edge[color=invis];2 -> 0 -> 3 -> 4;}
0 -> 0 [label="6: 0.1764"];
0 -> 4 [dir="both", color="yellow:blue", labeldistance="5", headlabel=<<font color="yellow">4: 0.1304</font>>, taillabel=<<font color="blue">6: 0.1237</font>>];
0 -> 3 [dir="both", color="blue:black", labeldistance="8", headlabel=<<font color="blue">5: 0.1551</font>>, taillabel=<<font color="black">6: 0.1658</font>>];
0 -> 1 [label="Z: 0.3893"];
4 -> 1 [label="Z: 0.4585"];
3 -> 4 [dir="both", color="green:red", labeldistance="5", headlabel=<<font color="green">4: 0.13</font>>, taillabel=<<font color="red">5: 0.05201</font>>];
3 -> 3 [label="5: 0.1038"];
3 -> 1 [label="Z: 0.4388"];
2 -> 0 [dir="both", color="yellow:blue", labeldistance="11", headlabel=<<font color="yellow">6: 0.1661</font>>, taillabel=<<font color="blue">7: 0.1489</font>>];
2 -> 4 [dir="both", color="black:red", labeldistance="5", headlabel=<<font color="black">4: 0.1295</font>>, taillabel=<<font color="red">7: 0.15</font>>];
2 -> 3 [dir="both", color="blue:green", labeldistance="8", headlabel=<<font color="blue">5: 0.2078</font>>, taillabel=<<font color="green">7: 0.1616</font>>];
2 -> 2 [label="7: 0.1406"];
2 -> 1 [label="Z: 0.356 "];
1 -> 0 [label="6: 0.1103"];
1 -> 4 [label="4: 0.2591"];
1 -> 3 [label="5: 0.1382"];
1 -> 2 [label="7: 0.08581 "];
1 -> 1 [label="Z: 0.1906"];
}
This produces:
Other ideas / improvements solicited...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With