Flowgraph
- D3Blocks.flowgraph(df, nodes=None, groups: dict = None, direction: str = None, layout: str = 'dagre', shape: str = 'process', color: str = 'group', cmap: str = 'Set2', edge_color: str = '#8c8c8c', nodesep: int = 40, ranksep: int = 70, edgesep: int = 20, ranker: str = 'network-simplex', curve: str = 'smooth', animate: bool = False, draggable: bool = True, show_edge_labels: bool = True, show_groups: bool = True, steps: list = None, font: dict = {'size': 13}, title: str = 'Flowgraph - D3blocks', filepath: str = 'flowgraph.html', figsize=[None, None], showfig: bool = True, overwrite: bool = True, notebook: bool = False, save_button: bool = True, show_side_panel: bool = True, show_top_panel: bool = True, dark_mode=True, color_background=None, return_html: bool = False, reset_properties: bool = True)
Flowgraph block: process flows and architecture diagrams.
Nodes are arranged in ranks along the flow direction with a layered layout, drawn as flowchart shapes and optionally nested in groups such as swimlanes, services or network boundaries. The input is either an edge list, a Mermaid flowchart or a Mermaid state diagram.
- Parameters:
df (pd.DataFrame, str or path-like) –
DataFrame with the edges. Required columns: ‘source’, ‘target’. Optional columns: ‘label’ (edge text), ‘weight’ (line width), ‘variant’, ‘style’ (‘solid’, ‘dashed’, ‘dotted’), ‘color’ and ‘animation’. A ‘source’ or ‘target’ may name a group in groups (one with member nodes and no entry in nodes); the edge is then drawn to the group box.
str: a Mermaid flowchart, e.g. ‘flowchart LR; A[Start] –> B{Valid?}’, a Mermaid state diagram (‘stateDiagram-v2’), or Markdown text containing a fenced Mermaid code block.
Path to a Markdown file (.md, .markdown) with a fenced Mermaid code block, so the same diagram renders on GitHub, or to a .mmd / .mermaid file. From Markdown, the first flowchart or state diagram block is used.
Node shapes, edge labels, dotted/thick links, (nested) subgraphs and linkStyle colours are converted; nodes, groups and direction override what it defines. State diagrams: transitions with labels, ‘[*]’ start/end (small circles), notes (shown in the state’s tooltip), direction and classDef colours; laid out ‘TB’ by default. Statements that do not parse or have no equivalent (click, links to subgraphs, …) raise a ValueError naming the line.
nodes (pd.DataFrame or dict, (default: None)) –
- Per-node attributes keyed by node name (a ‘name’ column or the index):
’label’: display text; use ‘n’ for line breaks.
’shape’: ‘process’, ‘decision’, ‘terminal’, ‘io’, ‘subprocess’, ‘database’, ‘queue’, ‘document’, ‘external’ or ‘circle’.
’group’: group (swimlane / boundary) the node belongs to.
’color’: node colour; overrides color.
’tooltip’: extra text or HTML shown on hover below the label.
groups (dict, (default: None)) – Group settings: {group: {‘label’: str, ‘parent’: str, ‘color’: hex}}. Use ‘parent’ to nest groups (e.g. a subnet inside a VPC). The short form {group: parent} is also accepted.
direction (str, (default: None)) – Flow direction: ‘LR’, ‘TB’ (or ‘TD’), ‘RL’ or ‘BT’. None: the direction of the Mermaid header, otherwise ‘LR’.
layout (str, (default: 'dagre')) –
‘dagre’: layered layout with smooth edges; small output (~0.5 MB).
’elk’: ELK layered layout with orthogonal edge routing and native nested groups; tidier for architecture diagrams, adds ~1.5 MB to the HTML.
shape (str, (default: 'process')) – Default shape for nodes without one.
color (str, (default: 'group')) –
‘group’: colour nodes by group.
’shape’: colour nodes by shape.
’#RRGGBB’: one colour for all nodes.
cmap (str, (default: 'Set2')) – Colormap for group / shape colouring.
edge_color (str, (default: '#8c8c8c')) – Default edge colour.
nodesep (int, (default: 40)) – Pixels between nodes in the same rank.
ranksep (int, (default: 70)) – Pixels between ranks.
edgesep (int, (default: 20)) – Pixels between parallel edges.
ranker (str, (default: 'network-simplex')) – dagre ranking algorithm: ‘network-simplex’, ‘tight-tree’ or ‘longest-path’.
curve (str, (default: 'smooth')) – Edge shape: ‘smooth’ (curved, or rounded corners with ELK) or ‘straight’.
animate (bool, (default: False)) – Animate pulses along the edges to show the direction of flow.
draggable (bool, (default: True)) – Nodes can be dragged; connected edges and groups follow.
show_edge_labels (bool, (default: True)) – Draw edge labels.
show_groups (bool, (default: True)) – Draw groups as containers (and keep their members together).
steps (list of dict, (default: None)) – Captioned walkthrough; “Walk through” in the top panel steps through it: [{‘title’: str, ‘caption’: str, ‘highlight’: {‘nodes’: […], ‘edges’: [(source, target), …]}}]. Each step highlights its nodes and edges, dims the rest and zooms to them. None: the “Trace” button walks the flow uncaptioned.
font (dict, (default: {'size': 13})) – Font properties.
title (str, (default: 'Flowgraph - D3blocks')) – Title of the figure.
filepath (str, (default: 'flowgraph.html')) – File path to save the output. None: return HTML only.
figsize (list, (default: [None, None])) – [width, height] in pixels. None: full window.
showfig (bool, (default: True)) – Open the chart in the browser.
overwrite (bool, (default: True)) – Overwrite an existing file.
notebook (bool, (default: False)) – Display inline in a Jupyter notebook, isolated in an iframe sized by figsize (default: full width x 650 px). The returned HTML is then that iframe.
save_button (bool, (default: True)) – Show the SVG/PNG save buttons.
show_side_panel (bool, (default: True)) – Show the left side panels (Export / Save, Layout, Legend).
show_top_panel (bool, (default: True)) – Show the top bar (logo, search, fit, theme).
dark_mode (bool or 'auto', (default: True)) –
- Initial theme; the theme button switches at runtime in every mode.
True: start in the dark theme.
False: start in the light theme.
’auto’: follow the operating system theme until the theme button is used.
color_background (list of str, str, or None, (default: None)) – Backgrounds for center / top / side panels as
[dark_hex, light_hex]. Named themes:'streamlit','darkblue'. None →['#222222', '#ffffff'].return_html (bool, (default: False)) – Return the HTML string.
reset_properties (bool, (default: True)) – Recompute node and edge properties from the input.
- Returns:
d3.node_properties (DataFrame of dictionary) – Node properties; edit and call d3.show() to update.
d3.edge_properties (DataFrame) – Edge properties; edit and call d3.show() to update.
d3.config (dictionary) – Configuration. d3.config[‘groups’] holds the group settings (merged with Mermaid subgraphs); edit and call d3.show(). Labels, nesting and colours are resolved from it on every draw.
Examples
>>> # Edge list with shapes and edge labels >>> import pandas as pd >>> from d3blocks import D3Blocks >>> d3 = D3Blocks(frame=False) >>> df = pd.DataFrame({'source': ['Start', 'Valid?', 'Valid?', 'Fix'], ... 'target': ['Valid?', 'Done', 'Fix', 'Valid?'], ... 'label': ['', 'yes', 'no', 'retry']}) >>> nodes = {'Start': {'shape': 'terminal'}, 'Valid?': {'shape': 'decision'}, ... 'Done': {'shape': 'terminal'}} >>> d3.flowgraph(df, nodes=nodes, direction='TB') >>> # Change a node and redraw >>> d3.node_properties['Fix']['color'] = '#e15759' >>> d3.show() >>> >>> # Mermaid diagram kept in a Markdown file (renders on GitHub too) >>> d3.flowgraph('docs/process.md') >>> >>> # Mermaid flowchart with a subgraph, laid out with ELK >>> d3.flowgraph(''' ... flowchart LR ... subgraph api [API] ... gw[Gateway] --> svc[Orders] ... end ... svc --> db[(Postgres)] ... svc -.->|events| q[[Worker]] ... ''', layout='elk')
References
Input Data
The input is either an edge list (DataFrame) or a Mermaid flowchart (string).
The edge list needs the columns source and target; all other columns are optional.
# source target label variant animation
# 0 start check None
# 1 check pick yes emphasis comet
# 2 check backorder no error None
# 3 backorder check retry async dots
Per-node attributes (label, shape, group, color, tooltip) are passed with nodes,
and group settings (label, parent, color) with groups.
Shapes:
process,decision,terminal,io,subprocess,database,queue,document,external,circle.Edge variants:
default,emphasis,security,async,error. Each sets a colour, line style and width; an edge’s owncolorandstyleoverride it.Animations:
pulse,dash,dots,cometfor the whole chart (animate=) or per edge (animationcolumn).
Process flow
import pandas as pd
from d3blocks import D3Blocks
edges = pd.DataFrame({
'source': ['start', 'check', 'check', 'fix'],
'target': ['check', 'done', 'fix', 'check'],
'label': ['', 'yes', 'no', 'retry'],
})
nodes = {
'start': {'label': 'Start', 'shape': 'terminal'},
'check': {'label': 'Valid?', 'shape': 'decision'},
'fix': {'label': 'Fix input'},
'done': {'label': 'Done', 'shape': 'terminal'},
}
d3 = D3Blocks(frame=False)
d3.flowgraph(edges, nodes=nodes, direction='TB')
# Change a node and redraw
d3.node_properties['fix']['color'] = '#e15759'
d3.show()
Mermaid input
Node shapes, edge labels, dotted (-.->) and thick (==>) links, &, chains,
nested subgraphs, links to and from subgraphs, node colours from style / classDef and edge
colours and dashes from linkStyle are converted.
Links to subgraphs
A link may name a whole subgraph, at either end and also between two subgraphs. It is drawn to the subgraph’s box border, as Mermaid draws it, with dagre and with ELK. Hovering the group lights the links of the group and of the groups nested in it; the trace walks through it like a node.
d3.flowgraph('''
flowchart LR
subgraph Workers ["Background workers"]
W1[scheduler]
W2[sync]
end
Workers --> PG[(PostgreSQL)]
''')
With a DataFrame, a source or target that names a group in groups= (one with member nodes
and no entry in nodes=) works the same way:
edges = pd.DataFrame({'source': ['Workers'], 'target': ['PG']})
nodes = {'W1': {'group': 'Workers'}, 'W2': {'group': 'Workers'}, 'PG': {'shape': 'database'}}
d3.flowgraph(edges, nodes=nodes, groups={'Workers': {'label': 'Background workers'}})
A link to an empty subgraph draws a node with the subgraph’s title. A link between a subgraph and
itself or its own content raises a ValueError, as there is no box border to draw it to.
Mermaid errors
All d3blocks Mermaid readers (flowcharts, state diagrams, sequence and erd) follow one
rule: every statement is understood, explicitly ignored, or raises a ValueError that names the
line, before any HTML is written. Nothing is dropped silently.
Ignored: blank lines,
%%comments,%%{init}%%directives and the accessibility metadataaccTitle/accDescr.Errors: statements that do not parse (for example
A[Start] --> B{ok?), a wrong first statement, anendwithoutsubgraph(or asubgraphwithoutend), a link between a subgraph and its own content, a linked subgraph id that is also given a label, shape,styleorclass, and Mermaid features without an equivalent here, such asclickand adirectioninside a subgraph.
Line numbers count from the first line of the diagram (in Markdown: of the fenced block).
d3.flowgraph('flowchart LR\n A[Start] --> B{ok?')
# ValueError: Mermaid flowchart line 2 could not be parsed: 'A[Start] --> B{ok?' (...)
d3.flowgraph('''
flowchart LR
start([Order received]) --> check{In stock?}
check -->|yes| pick[Pick & pack]
check -- no --> back[[Backorder]] -.->|restocked| check
subgraph wh [Warehouse]
pick --> ship[/Ship parcel/]
end
ship ==> done([Delivered])
''')
The diagram can also live in a Markdown file as a fenced mermaid block, so GitHub renders it
too; pass the file path (.md, .markdown, .mmd or .mermaid). From Markdown, the first
flowchart block is used.
d3.flowgraph('docs/order_process.md')
State diagrams
Mermaid stateDiagram and stateDiagram-v2 are read too, so lifecycle diagrams render with
the same layout, interaction and export as flowcharts. [*] becomes one start and one end
pseudo-state (small circles), transition labels are kept (everything after the first :), notes
are added to the state’s tooltip and classDef / class colours are applied. State diagrams are
laid out top to bottom unless the diagram has a direction statement or direction is
passed. Composite states, <<choice>>, state "x" as A and A : description raise a
ValueError naming the line.
d3.flowgraph('''
stateDiagram-v2
[*] --> pending : Signal created
pending --> awaiting_approval : Risk checks pass
pending --> cancelled : Strategy disabled
awaiting_approval --> approved : Operator approves
awaiting_approval --> rejected : Operator rejects
approved --> executed : Order sent to broker
executed --> [*]
rejected --> [*]
cancelled --> [*]
note right of awaiting_approval
Agent-generated signals
enter here directly
end note
classDef review fill:#e0f2fe,stroke:#0284c7
class awaiting_approval review
''')
From Markdown, the first flowchart or state diagram block is used; other diagram types are skipped.
Architecture diagram
Groups can be nested with parent. layout='elk' uses ELK’s layered layout with orthogonal
edge routing; it suits nested architecture diagrams but adds about 1.5 MB to the HTML file.
groups = {
'Cloud': {'label': 'Cloud account'},
'VPC': {'parent': 'Cloud'},
'App subnet': {'parent': 'VPC'},
'Data subnet': {'parent': 'VPC'},
}
nodes = {
'api': {'label': 'API', 'group': 'App subnet'},
'worker': {'label': 'Worker', 'group': 'App subnet'},
'db': {'label': 'PostgreSQL', 'shape': 'database', 'group': 'Data subnet'},
'bus': {'label': 'Event bus', 'shape': 'queue', 'group': 'Data subnet'},
'users': {'label': 'Users', 'shape': 'circle'},
}
edges = pd.DataFrame({
'source': ['users', 'api', 'api', 'bus'],
'target': ['api', 'db', 'bus', 'worker'],
'label': ['HTTPS', 'SQL', 'publish', 'consume'],
'variant': ['emphasis', 'default', 'async', 'async'],
})
d3.flowgraph(edges, nodes=nodes, groups=groups, layout='elk', animate='dots')
Jupyter and Streamlit
In a notebook, pass notebook=True; the chart is shown inline, isolated in an iframe sized by
figsize (default: full width x 650 px). See notebooks/flowgraph.ipynb.
d3 = D3Blocks(frame=False)
d3.flowgraph(edges, nodes=nodes, notebook=True, filepath=None, figsize=[None, 520])
In Streamlit, generate the HTML with return_html=True and embed it with st.iframe.
streamlit/flowgraph_streamlit_demo.py edits a Mermaid flowchart in the sidebar and
re-renders it with the chosen layout, direction and animation.
html = D3Blocks().flowgraph(flowchart, filepath=None, showfig=False, return_html=True)
st.iframe(html, height=700, width="stretch")
Walkthrough
steps adds a captioned walkthrough. ▶ Walk through in the top panel opens a caption bar with
the step title, the caption, “Step 3 of 9”, a row of step stops and Prev / Play / Next. Each step
highlights its nodes and edges, dims the rest and zooms to them. Keys: ← and → move, Space plays or
pauses, Esc closes. Play advances every 3 seconds and stops on the last step.
steps = [
{'title': 'Check', 'caption': 'Every order is validated first.',
'highlight': {'nodes': ['check'], 'edges': [('start', 'check')]}},
{'title': 'Retry', 'caption': 'Invalid input is fixed and checked again.',
'highlight': {'edges': [('check', 'fix'), ('fix', 'check')]}},
]
d3.flowgraph(edges, nodes=nodes, steps=steps)
Without steps the button is ▶ Trace, the uncaptioned walk through the flow. Unknown nodes or
edges and unsupported keys raise a ValueError with the step index. The same walkthrough is used by
sequence and erd.
Theme
The theme button (last on the right of the top panel) switches between dark and light at runtime.
dark_mode=True (default) starts dark, False starts light, and dark_mode='auto' follows the
operating system theme, also when it changes, until the theme button is used. In 'auto' mode a
?theme=light or ?theme=dark URL parameter picks the theme. Exports keep the theme shown.
Interaction
Hover a node to trace everything upstream and downstream; click to pin.
▶ Trace walks through the flow step by step (from the pinned node, or from all start nodes); with
stepsit is ▶ Walk through, the captioned walkthrough.Drag nodes; edges and groups follow. Reset layout recomputes the layout.
The Layout panel changes direction, spacing, font size, edge curve and animation.
The Legend panel lists groups and the edge variants in use.
Export to SVG, PNG or JSON (including computed positions).