Search code examples
pythonigraphgraph-drawing

igraph: How to fix node position when drawing incrementally growing subgraphs of the same graph


I have a graph where I have previously precomputed the positions of the nodes by running ForceAtlas2 in Gephi and then I attempt to draw with ìgraph in python. Each node has a date attribute so I iterate over all years, compute the corresponding subgraphs and draw them to create an animation effect.

However as nodes keep being added to the graph, the previous nodes don't necessarily keep their old positions, similarly to what is described in this post

My code is as follows:

colors = [color_list[int(g.vs[v]["Modularity Class"])] for v in range(0, len(g.vs))]
label_sizes = [sz / 4.0 for sz in g.vs["size"]]

nodes_in_years = defaultdict(list) # keeps a list of nodes per year
for v in g.vs:
    year = int(v["date"][:4]) # convert the first 4 digits of the date to year
    nodes_in_years[year].append(v)

nodes_incremental = []
for y, nodes in nodes_in_years.items():
    nodes_incremental += nodes
    h = g.subgraph(nodes_incremental)

    plot(h, "graph-igraph%d.png"%y,
         bbox=(640,480),
         vertex_color=colors,
         vertex_label_size=label_sizes,
         keep_aspect_ratio=False,
          )

The following are two consecutive snapshots. graph 2001 graph 2002

In the second snapshot nodes are slightly "squeezed" as more nodes are added to the left.

How can I keep the nodes at fixed positions? I tried with xlim setting and ylim but I might not be setting the values right


Solution

  • xlim and ylim are for the R interface of igraph; they have no effect in Python. The usual trick to employ is to find the minimum and maximum X and Y coordinates across all snapshots, and then place two fake vertices (with their shape attribute set to None) in the upper left and lower right corners of the layout. Make sure that you include these fake vertices in all snapshots with the same coordinates - this will ensure that the layouts are scaled exactly the same way in each snapshot to fit the bounding box that you specify.

    If you did not use the shape attribute with your current layout, note that adding a shape attribute to the fake vertices will also add the shape attribute (with the default value of None) to the "real" vertices, so you should manually set the shape attribute of all vertices except the two fake ones to "circle".