I'm trying to create a graph to represent transitions between different states of a system. I would like to represent the time the systems spent in a state with the size of the vertex and the frequency of transition between two states with the thickness of the edge connecting the two vertices. In short I need to control the size of vertices and the thickness of edges.
Now that I grasp the difference between Graph and GraphPlot a bit better, I wanted to implement this using the newer Graph
functunality, specifically VertexSize
and EdgeStyle
.
Here is my clumsy attempt:
trans = Uncompress[FromCharacterCode[
Flatten[ImageData[Import["https://i.stack.imgur.com/YX8NN.png"],"Byte"]]]];
l = VertexList[Graph[trans]];
(*Weigths for vertices*)
r = RandomReal[{0.5, 1}, Length[l]];
vs = Transpose@{l, r} /. List[a_, b_] -> Rule[a, b];
(*Adjust font size*)
vls = Transpose@{l, r} /.
List[a_, b_] -> Rule[a, Directive[Black, Bold, 20*b]];
(*Weigths for line thicknes*)
rr = RandomReal[{0.1, 1}, Length[DeleteDuplicates@trans]]/100;
es = (First@# -> Directive[Thickness[Last@#], Opacity[.5]]) & /@
Transpose@{DeleteDuplicates@trans, rr};
g = Graph[DeleteDuplicates@trans,
VertexLabels -> Placed["Name", Center],
VertexShapeFunction -> "Capsule", VertexSize -> vs,
VertexLabelStyle -> vls, EdgeStyle -> es,
EdgeShapeFunction ->
GraphElementData["ShortUnfilledArrow", "ArrowSize" -> 0.03]]
But the result is useless (the text is not readable and it's not clear from where to where the arrows are going):
How can I either fix this graph so that it's readable or implement variable vertex sizes and variable edge thickens using GraphLayout
?
EDIT @kguler's comment helps. so using:
esf = Function[
a, (First@
a -> ({Arrowheads[{{.03, 1}}],
Arrow[#1, {.10 + 6 Last@a, .15}]} &))] /@
Transpose@{DeleteDuplicates@trans, rr};
g = Graph[DeleteDuplicates@trans,
VertexLabels -> Placed["Name", Center], VertexSize -> vs,
VertexLabelStyle -> vls, EdgeStyle -> es, EdgeShapeFunction -> esf(*,
EdgeShapeFunction->GraphElementData["ShortUnfilledArrow",
"ArrowSize"->0.03]*)]
I get , which is almost usable.
Is there perhaps a way to draw vertices on top of the edges?
Graph
you could doVertexList[Graph[trans]]
. $\endgroup$Property
). $\endgroup$EdgeShapeFunction
to something likeEdgeShapeFunction -> ({Arrowheads[{{.03, 1}}], Arrow[#1, {.1, .15}]} &)
to avoid too much traffic on top of vertices. $\endgroup$Circle
the following works:EdgeShapeFunction -> ({Arrowheads[{{.03, 1}}], Arrow[#1, {.2 #2[[1]] /. vs, .2 #2[[2]] /. vs}]} &)
. $\endgroup$