Question

I have a (directed acyclic) graph, such that each node have a discrete time-stamp i.e., each node is labeled with a number : 1,2,3,4...

The graph might have more than one component, and the time-stamp is increasing with the direction of the graph.

I have the graph as netowrkx object, and now I want to create a figure in python with the graph s.t. a node's height is determined by it's time-stamp (lower time-stamps at the top and higher at the bottom and nodes with the same time-stamps are at the same height). Meaning that for instance, 2 components may "begin" (their root's height) at different initial heights if their time-stamps are different.

on the other hand, given node A labeled with time = 4, and node B, labeled 5, I want B to be lower in the figure.

3rd example: if 2 nodes are children of a third node but they were created in different times - the edge will be longer for the latest one, s.t. each children will be in its own time-level.

write now, the code I have is very simple:

import networkx as nt
import matplotlib.pyplot as plt

graph = networkx.DiGraph() 
self.graph.add_node("A", time = 1)
...# Add more nodes
graph.add_edge("A","B")
...# Add more edges
plt.figure(1,figsize=(30,10))
pos=nt.graphviz_layout(graph,prog='dot')
networkx.draw(graph,pos,with_labels=False,arrows=True, node_size = 80)

(I don't have enough reputation to upload image of the results... :-) )

How can I draw this in Python? Which package can help me here?

Was it helpful?

Solution

The positions of the nodes are defined in a dictionary, with key the name of the node and value a tuple with the x and y coords.

You can see this by printing the pos variable once created:

pos=nt.graphviz_layout(graph,prog='dot')
print pos

# EXAMPLE RESULT
{'A': (51.5, 15.3), 'B': (20.0, 60.4)}

A higher value in the y coordinate will place the node higher in the graph. So if you want the root nodes to be at the top (lower time stamp value), just use the negative of the time stamps as -1 will be higher than -2.

To automate the process of placing the nodes, you need some equation based on time.

pos = {}
for key, value in graph.node.items():
    height = value['time']    # Time value as defined when adding the node `key`
    pos[key] = (50, -height)

This will place the nodes vertically, based on their time stamps. So the distance between two nodes created at times 1 and 4 and will be twice as large than two nodes created at times 1 and 2. In this example I kept the horizontal component static (50) and all nodes will end up in a vertical line. You should be able to vary that according to your needs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top