Streamlit Graphviz_chart() does not support node positions

I have used graphviz_chart() function to display graphviz charts but it does not accept Node positions (x,y) I tried to search around but did not find solution anywhere. below is my code. some one know such solutions.

graph.node(v, label=label, shape='record', pos=f'{x},-{y}!')

it display graph but only in sequential order. does not position the node where I fix it.

Sadly, this is an old bug/limitation of st.graphviz_chart

In short, a different engine is required by graphviz to render nodes in fixed positions (check pos | Graphviz for details), however, none of them are supported by st.graphviz_chart.


Related topic:

1 Like

I used neato which supports positioning. any idea shall I switch to anyother graph libraray? I need to draw flow chart at specified positions.

I’d export the graph as an image and then display that image using st.image (which is what st.graphviz_chart does anyway iinw). Check the graphviz.pipe and graphviz.render methods from API Reference β€” graphviz 0.20.1 documentation.

Here a small example:

import streamlit as st
import graphviz
from io import BytesIO

engines = ['circo', 'dot', 'fdp', 'neato', 'osage', 'patchwork', 'sfdp', 'twopi']
shapes = ['note', 'egg', 'star', 'house', 'box']

"# Alternative to `st.graphviz_chart`"

cols = st.columns([1,2])

with cols[0]:
    engine = st.selectbox("Engine:", engines)
    shape = st.selectbox("Shape:", shapes)
    dpi = st.slider("dpi:", 10, 600, 200, 10)

## Create graph
graphviz.set_default_engine(engine=engine)
g = graphviz.Digraph('Round-table', engine=engine)

## Global graph attributes
g.graph_attr['pin'] = 'true'    # <-- Fixed position of nodes
g.graph_attr['dpi'] = f'{dpi}'  # <-- Sets the PNG resolution
g.graph_attr['rankdir'] = 'LR'  # <-- Left to right order
g.graph_attr['bgcolor'] = 'transparent'

## Global node attributes
g.node_attr['shape'] = shape
g.node_attr['fillcolor'] = 'lightgrey'
g.node_attr['style'] = 'filled'

## Global node attributes
g.edge_attr['color'] = 'blue'

## Add nodes and edges
for i in range(4):
    g.node(str(i), label=f"{shape} {i}", pos=f'{i}, -{i}!')
    
    if i < 3:
        g.edge(f"{i}", f"{i+1}")

## Export as image
with BytesIO() as f:
    f.write(g.pipe(format='png', engine=engine))
    
    with cols[1]:
        st.image(f, use_column_width=True, caption="Awesome graph!")




1 Like