Graph drawing: overlay possible?

Hi!

I was wondering if it is possible to overlay two drawings of the same graph where I use different color-coded vertex sizes? Theses colors would need to be transparent and the graph layout must match in each drawing. Is there an easy way of doing so with graph-tool?

Thanks!

Regards,

Hi Sebastian,

I was wondering if it is possible to overlay two drawings of the same
graph where I use different color-coded vertex sizes?

The only way of _actually_ overlaying (without modifying the graph)
would be to create two png or svg figures, and overlaying them with some
graphics software/library.

If you want to modify the graph, you can draw it first to obtain the
positions, then duplicate the vertices and/or edges, copy the positions
and set the colors you want, and then you have your "overlay".

Theses colors would need to be transparent and the graph layout must
match in each drawing.

Transparent colors are no problem, as well as matching the layout (you
just need to pass the 'pos' parameter, and set 'pin=True' so that the
positions remain fixed).

Cheers,
Tiago

Hi,

I am quite new to graph-tool and mostly use it for drawing at the moment.
Thanks Tiago for all the great work you put into graph-tool!

Apologies for hijacking this thread - I hope this okay as my question is
basically the same that Sebastian had.

Tiago Peixoto wrote:

Theses colors would need to be transparent and the graph layout must
match in each drawing.

Transparent colors are no problem, as well as matching the layout (you
just need to pass the 'pos' parameter, and set 'pin=True' so that the
positions remain fixed).

That's exactly what I tried, but for me, every time I call gt.graph_draw, I
get a new layout.

Here's my code:

#create network and properties...
#first plot. this works fine
positions = gt.graph_draw(network, vcolor=colorProperties, vcmap=colorMap,
vnorm=False, vorder=plotOrder, output='out0.png')

# change a few values in colorProperties and plotOrder

# now draw again
gt.graph_draw(network,pos=positions,pin=True,vcolor=colorProperties,vcmap=colorMap,vnorm=False,output='out1.png')

This might not be very helping, but I gave up back then, when I had the problem. A solution would be great though…

Cheers

I think I found a way forward - may not be perfect, but works for the
time being.

It looks like pin only works with neato and fdp - see
http://www.graphviz.org/doc/info/attrs.html#d:pin

So I added layout='neato' to graph_draw, and that seems to do the trick.
Unfortunately, the canvas size seems to change (even though I specified
size=(15,15) for the initial layout and for the later call). My current
workaround is to simply redraw the graph with neato and overwrite the
output file.

One thing that suprised me is that pinning doesn't make things any
faster. My network has almost 10000 nodes - does it really take most of
the time to create output rather than performing the actual layout?

Cheers,
Steffen

Strange, I cannot reproduce this at all... For me, I get always the same
layout.

What version of graphviz do you have insalled?

Cheers,
Tiago

I think I found a way forward - may not be perfect, but works for the
time being.

It looks like pin only works with neato and fdp - see
Attributes | Graphviz

So I added layout='neato' to graph_draw, and that seems to do the
trick.

The graph_draw() function defaults to 'neato' if the graph is smaller
than 1000 nodes, and uses 'sfdp' otherwise. And indeed, it seems like
'sfdp' ignores the pin property. This is a graphviz limitation.

Unfortunately, the canvas size seems to change (even though I
specified size=(15,15) for the initial layout and for the later
call). My current workaround is to simply redraw the graph with neato
and overwrite the output file.

Unfortunately, graphviz gives very little control on the total canvas
size, and likes to crop things. I find it very annoying, but I don't
know how to force graphviz to do the right thing.

One thing that suprised me is that pinning doesn't make things any
faster. My network has almost 10000 nodes - does it really take most
of the time to create output rather than performing the actual layout?

I notice a _huge_ difference when running 'neato' with pinning
vs. without. But maybe you can improve things further by limiting the
total number of iterations with the 'maxiter' parameter.

Cheers,
Tiago

Strange, I cannot reproduce this at all... For me, I get always the same
layout.

What version of graphviz do you have insalled?

I'm on version 2.26.3 (20100126.1600) - the one in the Ubuntu Natty repos.

The graph_draw() function defaults to 'neato' if the graph is smaller
than 1000 nodes, and uses 'sfdp' otherwise. And indeed, it seems like
'sfdp' ignores the pin property. This is a graphviz limitation.

Maybe you could add another check to draw/__init__.py at line 312:

layout = "neato" if g.num_vertices() <= 1000 else "fdp" if pos is not
None and pin else "sfdp"

Unfortunately, graphviz gives very little control on the total canvas
size, and likes to crop things. I find it very annoying, but I don't
know how to force graphviz to do the right thing.

At least when I set the canvas size for neato with size=(15,15), I
always get the same size in the end.

One thing that suprised me is that pinning doesn't make things any
faster. My network has almost 10000 nodes - does it really take most
of the time to create output rather than performing the actual layout?

I notice a _huge_ difference when running 'neato' with pinning
vs. without. But maybe you can improve things further by limiting the
total number of iterations with the 'maxiter' parameter.

Thanks, setting maxiter=1 made things faster (subjectively, I haven't
done timings).
What I meant originally was that the difference between sfdp without pin
and neato/fdp (I tried both now) with pin isn't as big as I thought. My
naive expectation was that it takes most of the time to do the layout,
so if we tell graphviz where to put the nodes, the rest should be a lot
quicker.

Best,
Steffen

The graph_draw() function defaults to 'neato' if the graph is smaller than 1000 nodes, and uses 'sfdp' otherwise. And indeed, it seems like 'sfdp' ignores the pin property. This is a graphviz limitation.

Maybe you could add another check to draw/__init__.py at line 312:

layout = "neato" if g.num_vertices() <= 1000 else "fdp" if pos is not None and pin else "sfdp"

Yes, something like this would be a good idea.

Thanks, setting maxiter=1 made things faster (subjectively, I haven't
done timings). What I meant originally was that the difference
between sfdp without pin and neato/fdp (I tried both now) with pin
isn't as big as I thought. My naive expectation was that it takes most
of the time to do the layout, so if we tell graphviz where to put the
nodes, the rest should be a lot quicker.

Although the difference between sfdp and fdp/neato is very noticeable
for larger graphs, I would expect that both fdp/neato with pin=True
would be _much_ faster than sfdp, since the layout algorithm is not
run. In my experience, this is always what I found. I would be
interested in understanding why you perceive this not to be the
case... How long does it actually take to plot with sfdp and neato with
pinning?

Cheers,
Tiago

I've just done a few timings using layout='neato' (or
layout='fdp'),pos=positions,pin=True,maxiter=0.
This takes about 11 seconds for my network. I had used maxiter=1
earlier, and that made neato a lot slower (more than a factor of 2)
while fdp's performance didn't change much. sfdp takes about 15 seconds.
In all cases, I specified vcolor, vcmap and vorder.
So you're completely right: neato/fdp are a lot faster given the layout
and the right arguments.

I also experimented with matplotlib - given that I got the positions out
of graph-tool/graphviz, the rest can also be done there. The speed is a
little better there - it takes just under 10 seconds. Also, I want to do
many plots with the same layout (just different vertex colours), so I
think matplotlib is more convenient for me. I can plot the network once
and afterwards only draw the vertices whose colour changes, and then use
imagemagick/composite to do the overlay.

Cheers,
Steffen