diff --git a/auxiliary/libs/signalflow_visualisation/__init__.py b/auxiliary/libs/signalflow_visualisation/__init__.py
new file mode 100644
index 00000000..0faddf8c
--- /dev/null
+++ b/auxiliary/libs/signalflow_visualisation/__init__.py
@@ -0,0 +1,80 @@
+import json
+import networkx as nx
+from IPython.display import SVG
+from signalflow import Patch
+
+def visualise_patch_structure(patch: Patch):
+ """
+ Renders the structure of a patch as a directed graph.
+
+ Requires:
+ - networkx
+ - pygraphviz (https://github.com/pygraphviz/pygraphviz/issues/11)
+
+ Args:
+ patch (Patch): The patch to diagram.
+
+ Returns:
+ An IPython SVG object that can be rendered in a notebook.
+
+ TODO: Implement support for cyclical graphs (requires reformulating JSON using JSON pointers)
+ """
+
+ G = nx.DiGraph()
+
+ def label_map(label):
+ lookup = {
+ "add": "+",
+ "multiply": "×",
+ "subtract": "-",
+ "divide": "÷"
+ }
+ if label in lookup.keys():
+ return lookup[label]
+ else:
+ return label
+
+ spec = patch.to_spec()
+ structure = json.loads(spec.to_json())
+ nodes = structure["nodes"]
+ for node in nodes:
+ node_label = node["node"]
+ node_label = label_map(node_label)
+ node_label = "%s" % node_label
+
+ node_label += "
"
+ for input_key, input_value in node["inputs"].items():
+ if not isinstance(input_value, dict):
+ node_label += "
%s = %s" % (input_key, round(input_value, 7))
+ node_label += ""
+
+ # special graphviz syntax for enabling HTML formatting in node labels
+ node_label = "<%s>" % node_label
+ G.add_node(node["id"], label=node_label)
+ for node in nodes:
+ for input_key, input_value in node["inputs"].items():
+ if isinstance(input_value, dict):
+ label = ""
+ if not input_key.startswith("input"):
+ label = input_key
+ # white background
+ # label = "<
%s |