Bokeh network graph does not support self loop edges

Hi,

Does bokeh not support self loop edges in network graphs? I am trying to render graphs where some nodes have self loops. Notebook example code is attached.

import random

import networkx as nx

from bokeh.plotting import figure, from_networkx

from bokeh.models import (
    ColumnDataSource,
    Plot,
    Scatter,
    Range1d,
    LabelSet
)

from bokeh.io import show, output_notebook
output_notebook()

def generate_random_color():
    """Generates a random color in hex format."""
    r = random.randint(0, 255)
    g = random.randint(0, 255)
    b = random.randint(0, 255)
    return "#{:06x}".format(r << 16 | g << 8 | b)


def generate_random_list_of_colors(n):
    """Generates a random list of n colors in hex format."""
    colors = []
    for i in range(n):
        colors.append(generate_random_color())
    return colors

generate_random_color()

def generate_graph():
    G = nx.fast_gnp_random_graph(10, 0.01, 26, True)
    return G

G = generate_graph()
G.add_edge(3,3)
G.add_edge(5,5)
G.edges

def generate_graph_render():
    G = generate_graph()
    graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))
    
    graph_renderer.node_renderer.data_source.data["colors"] = (
        generate_random_list_of_colors(len(G))
    )
    graph_renderer.node_renderer.glyph = Scatter(size=30, fill_color="colors")
    
    x, y = zip(*graph_renderer.layout_provider.graph_layout.values())
    node_labels = list(G.nodes())
    label_set_source = ColumnDataSource(
        {"x": x, "y": y, "name": [node_labels[i] for i in range(len(x))]}
    )
    
    label_set_renderer = LabelSet(
        x="x",
        y="y",
        text="name",
        source=label_set_source,
        background_fill_color="white",
        text_font_size="15px",
        background_fill_alpha=0.7,
    )
    
    return graph_renderer, label_set_renderer

print("In Bokeh App")

plot = figure(
    x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1),
    title="Bokeh Server App for Graph")


graph_renderer, label_set_renderer = generate_graph_render()
plot.renderers.append(graph_renderer)
plot.renderers.append(label_set_renderer)


show(plot)

graph_renderer, label_set_renderer = generate_graph_render()
print(graph_renderer.edge_renderer.data_source.data)

Versions :

(base) jupyter@bokeh-notebooks:~$ pip freeze | grep bokeh
bokeh==3.4.0
jupyter_bokeh==4.0.1



Hi @Bryan , sorry to tag you but was doing a quick followup on this topic.

@rusty-ai Please note that I am not always here, and there is no SLA for response time (certainly not only a day). [1]

Bokeh does not currently support self-edges for graph renderers. That’s because the user provides the edge renderer, and there is not actually any guarantee that the renderer that the user supplies is capable of drawing “loops”. Adding such loops (or perhaps some other way to indicate self-edges) will probably have to be special cased in some way, but this will require new development. Please feel free to open a GitHub Issue to request this feature, since AFAICT no-one has actually yet done so.


  1. In fact later this year I will be 100% offline from here and everywhere else, for nearly an entire month. ↩︎

Thanks for the reply @Bryan. Sorry again for tagging you for a response and noted your point on the SLA. I will try to fiddle around with edge_renderer.data_source and also create a github issue.

1 Like