1

I am trying to annotate a network graph which comes from NetworkX and which is visualised in Bokeh. I was able to successfully add the labels to the ColumnDataSource, and have them appear on the figure, but the coordinates appear to be wrong as the labels are not lined up with the nodes. Any help would be greatly appreciated.

from bokeh.io import show
from bokeh.plotting import figure
from bokeh.models.graphs import from_networkx
from bokeh.models import ColumnDataSource, LabelSet


def visualise_graph(G):
    plot = figure(title="Title", tools="", x_range=(-1.5, 1.5),
              y_range=(-1.5, 1.5), toolbar_location=None)
    graph = from_networkx(G, nx.spring_layout)
    plot.renderers.append(graph)
    return plot


def prepare_labels(G, plot):
    pos = nx.spring_layout(G)
    x, y = zip(*pos.values())
    node_labels = nx.get_node_attributes(N, 'label')
    source = ColumnDataSource({'x': x, 'y': y,
                               'label': [node_labels[i] for i in range(len(x))]})
    labels = LabelSet(x='x', y='y', text='label', source=source,
                      background_fill_color='white')
    plot.renderers.append(labels)
    return plot

 plot = visualise_graph(N)
 plot_w_labels = prepare_labels(N, plot)
 show(plot_w_labels)

3 Answers3

0

I discovered the problem which was that I was using nx.spring_layout() to get the coordinates which actually generates a new graph with new coordinates. Instead I pulled the coordinates from the Bokeh figure using .layout_provider.graph_layout and it now works as desired.

0

My first ever post in stackoverflow so dont shoot me. Required change is smthg like this:

#draw graph with some layout
graph_renderer = from_networkx(graph_to_plot, nx.fruchterman_reingold_layout(graph_to_plot), scale=1, center=(0, 0))    
#x, y = zip(*pos.values())
x,y=zip(*graph_renderer.layout_provider.graph_layout.values())
graph_renderer.node_renderer.data_source.data['x']=x
graph_renderer.node_renderer.data_source.data['y']=y
.
.
label=LabelSet(x='x', y='y', text='index',level='glyph', source=graph_renderer.node_renderer.data_source)
Bob
  • 1
0

@user2892709 - This is for you.

First, extract the coordinates for the nodes using graph_renderer.layout_provider.graph_layout

graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))

pos = graph_renderer.layout_provider.graph_layout
x,y=zip(*pos.values())

Then add those values to LabelSet()

source = ColumnDataSource({'x':x,'y':y, 'field': <your_node_list>})
labels = LabelSet(x='x', y='y', text='field', source=source)

Finally, you can add the values to the graph using:

plot.renderers.append(graph_renderer)
plot.renderers.append(labels)