Generate and render optionally themed GraphViz diagrams with simple, easy to maintain code.
Project description
Generate and render optionally themed GraphViz diagrams with simple, easy to maintain code.
The heart of gvdot is class Dot, a DOT language graph expression.
Applications create diagrams using dot object methods, then either convert the
object to a DOT language string or render it as SVG or an image. Users can
also interactively display dot objects in notebooks.
Example
Suppose we want to generate diagrams of non-deterministic finite automata like this
represented as instances of
@dataclass
class NFA:
alphabet : str
delta : dict[str, list[list[str]]]
final : list[str]
start : str
where delta["q"][i] is the list of states reached from $q$ by the
$i^\text{th}$ input alphabet symbol.
We start by defining a theme, a normal dot object from which other dot objects can inherit graph attributes, default attributes, and roles.
nfa_theme = (Dot()
.all_default(fontsize=12)
.node_default(shape="circle", style="filled", fillcolor="khaki")
.node_role("init", label="", shape="none", width=0, height=0)
.node_role("final", shape="doublecircle", penwidth=1.25)
.graph(rankdir="LR", labelloc="t", fontsize=16))
A gvdot role is a collection Graphviz attribute values applications can assign to diagram elements by name.
Having isolated presentation attributes in a theme, our generation code is clean and easy to maintain.
def nfa_diagram(nfa:NFA, title:str):
dot = Dot(directed=True).use_theme(nfa_theme)
dot.graph(label=Markup(f"<b>{title}<br/></b>"))
dot.node("_init_", role="init")
dot.edge("_init_", nfa.start)
for state in nfa.final:
dot.node(state, role="final")
for state, transitions in nfa.delta.items():
merged = defaultdict(list)
for index, targets in enumerate(transitions):
for target in targets:
merged[target].append(
nfa.alphabet[index-1] if index > 0 else 'ε')
for target, symbols in merged.items():
dot.edge(state, target, label=", ".join(symbols))
return dot
We can render and save the diagram above with
example = NFA("01", {
"s0": [["q0", "r0"], [], []],
"q0": [[], ["q1"], ["q0"]],
"q1": [[], ["q1"], ["q2"]],
"q2": [[], ["q3"], ["q0"]],
"q3": [[], ["q1"], ["q4"]],
"q4": [[], ["q4"], ["q4"]],
"r0": [[], ["r0"], ["r1"]],
"r1": [[], ["r0"], ["r2"]],
"r2": [[], ["r3"], ["r1"]],
"r3": [[], ["r3"], ["r3"]],
}, ["q4","r0","r1","r2"], "s0")
with open("example.svg","w") as f:
print(nfa_diagram(example,"Example NFA").to_svg(), file=f)
In a notebook, we can directly show the diagram from a cell containing
nfa_diagram(example,"Example NFA").show()
You can find this NFA example and others in the examples directory.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gvdot-0.9.1.tar.gz.
File metadata
- Download URL: gvdot-0.9.1.tar.gz
- Upload date:
- Size: 14.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
119e20df97191d6a22d10c78d1c5915cfc3161f49527f03478ab86daf8ca5ea0
|
|
| MD5 |
f2a82d736edc1d8d001d45d876887daf
|
|
| BLAKE2b-256 |
64145989df59d728af7936d1c4f449f61b588b48a04cee469dac1445bfd4be98
|
File details
Details for the file gvdot-0.9.1-py3-none-any.whl.
File metadata
- Download URL: gvdot-0.9.1-py3-none-any.whl
- Upload date:
- Size: 14.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71ce46cc44160d99115a8b94535d2fb8479e5e6c30c40781b8b1ebb2e34cf5ed
|
|
| MD5 |
abe4586ca93e91fbbda6dada565efdbd
|
|
| BLAKE2b-256 |
d59bc5bb6374d068705bf0f930ba25feb9418009a8bb672a4666af04d5abdcf3
|