# Plotting a weighted tree graph

I am trying to plot a weighted graph using `SimpleWeightedGraphs` using `GraphPlot`.

``````g = SimpleWeightedGraph(5)
gplot(g)
``````

But, I would like to have it (a) as a tree with vertex 1 as the root, and (b) the edge’s thickness are as per the weights assigned to them. How can I do it?

``````gplot(g, nodelabel=vertices(g), edgelinewidth=weight.(edges(g)))
``````

3 Likes

Thank you! Could you please also address the problem that I would like it to have a tree structure, rather than a star?

I don’t think `GraphPlot.jl` can do tree layout. But Home · NetworkLayout.jl can. It is best integrated with `GraphMakie.jl` though.

Yes, I don’t see any tree layout or layered layout, that could be a good addition to GraphPlot

Thank you, I will check them.

If you want to explore even more possibilities that are possibly still experimental () , you could try Karnak.jl:

``````using Graphs
using SimpleWeightedGraphs
using Karnak

g = SimpleWeightedGraph(5)

@drawsvg begin
background("black")
sethue("gold")
drawgraph(g,
layout=vcat(
Point(0, -200), # point 1 is at the top
between.(Point(-200, 150), Point(200, 150), range(0, 1, length=4))
),
vertexshapesizes = 20,
edgestrokeweights =
(n, s, d, f, t) -> 2get_weight(g, s, d)
)
end
``````

This is merely passing some calculated positions for the vertices.

If you want to use the `buchheim` algorithm from NetworkLayout, you can do it like this;

``````g = SimpleWeightedDiGraph(5)    # must be a Directed Graph

@drawsvg begin
background("black")
sethue("cyan")
drawgraph(g,
layout=buchheim,
edgestrokeweights =
(n, s, d, f, t) -> get_weight(g, s, d)
)
end
``````

The `NetworkLayout.Buchheim()` algorithm lets you also specify the vertex spacing:

``````      ...
layout=Buchheim(nodesize=[1.0, 4.0, 8.0, 16.0]),
...
``````

3 Likes

Thank you so much!

1 Like

As other people mentioned, you can also use GraphMakie.jl

`Bucheim` breaks with your graph because it assumes double edges and a node cannot have multiple parent nodes.
If this is not a deal breaker you can work it around with `SimpleWeightedDiGraph`:

``````using GraphMakie

g = SimpleWeightedDiGraph(5)

edws = [get_weight(g, e.src, e.dst) for e in edges(g)]

graphplot(g, layout=NetworkLayout.Buchheim(), edge_width=edws, arrow_size=5 .+ 5 .* edws)
``````

If `SimpleWeightedDiGraph` is a deal breaker, you can of course get around that by being a little bit more verbose, i.e. making a directed graph representation just for plotting:

(maybe there is an easier way, but that came on top of my head)

``````using SparseArrays

g = SimpleWeightedGraph(5)

# directed graph equivalent just for plotting
sdg = let
[adg[i,j] = 0.0  for i in vertices(g) for j in vertices(g) if i > j];
end

edws = [get_weight(g, e.src, e.dst) for e in edges(sdg)]

# same plotting as before with the directed representation
graphplot(sdg, layout=NetworkLayout.Buchheim(), edge_width=edws, arrow_size=5 .+ 5 .* edws)
``````

Hi, thank you! I was wondering if there is any way to assign edge styles, like dash, dashdot etc.? I looked up the documentation, but not sure I see anything that helps! Also how to save the graph as a pdf?

You can save the graph as every figure in the `Makie` ecosystem.
For example when using the `CairoMakie` backend

``````using CairoMakie
f,a,p = graphplot(sdg, layout=NetworkLayout.Buchheim(), edge_width=edws, arrow_size=5 .+ 5 .* edws)
save("mygraphplot.pdf", f)
``````

`GraphMakie` uses the `linesegments` function in order to plot edges. By using the `edge_attr` attribute, you can pass whatever namedtuple that will be forwarded to the `linesegments`. For example if you want dashed edges you can do:

``````f,a,p = graphplot(sdg, layout=NetworkLayout.Buchheim(), edge_width=edws, arrow_size=5 .+ 5     .* edws, edge_attr=(linestyle=:dash,))
``````

Be careful of the single-namedtuple ending with a comma.

Thank you! This helps. One final thing, is there any attribute by which I can control the edge length? I mean the distance between the nodes, the default seems too long.

If you want a different layout you need to modify the layout function or pass in different parameters as defined e.g. in `Buchheim` and demonstrated by cormullion.

But I think what you really want is a different aspect of your plotted data.
No matter how closely you will plot the children with the `nodesize` from `Buchheim`, `Makie` will always zoom, as a result always looking the same. But you can change the aspect ratio, e.g.:

``````f = Figure()
#  width of three times the height.
ax = Axis(f[1,1], aspect=AxisAspect(3))
# same plot command
graphplot!(ax, sdg, layout=NetworkLayout.Buchheim(), edge_width=edws, arrow_size=5 .+ 5 .* edws, edge_attr=(linestyle=:dash,))
``````

1 Like

Thank you! Also, specifying the `width` of the axis makes it look a little nicer!