Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Generating a better looking family tree-style graph in Python
My goal
I'm looking for a way to programatically generate a visual representation of interlinked sections in a text file (preferably in svg format), with particular aesthetic considerations.
The graph should go from left to right, and consist of rectangular nodes connected by lines - each of which links to an arbitrary number of other ones (usually 0-3, sometimes as high as 10).
This is an almost perfect example of what the output should look like. In my mind, I'm picturing the section numbers below the rectangles and some descriptive text inside them. I don't care about the circles/dots, but the way the lines are drawn between the rectangles is precisely what I want in my graph.
The problem/my attempts
I've been experimenting with different graph-making software, but I'm having trouble getting the graph to look exactly how I want, particularly with respect to how the connections between nodes are drawn.
I started with Graphviz and ultimately ended up with the following code:
import graphviz
treeView = graphviz.Digraph(filename='Graphviz', format='svg', node_attr={'shape': 'record', 'height': '.1'}, edge_attr={'dir': 'none'})
treeView.attr(rankdir='LR', splines='ortho')
treeView.node('1', 'Start')
treeView.node('2', 'Section 2')
treeView.node('3', 'Section 3')
treeView.node('4', 'Section 4')
treeView.node('5', 'Section 5')
treeView.node('6', 'Section 6')
treeView.node('7', 'Section 7')
treeView.node('8', 'Section 8')
treeView.node('9', 'Section 9')
treeView.edge('1', '5')
treeView.edge('1', '2')
treeView.edge('2', '3')
treeView.edge('2', '4')
treeView.edge('3', '9')
treeView.edge('3', '8')
treeView.edge('5', '7')
treeView.edge('5', '6')
treeView.view()
However, the ortho splines apparently don't play nicely with the head/tailports based on my research, which makes the output look really bad unless it's in polyline, and even then the lines aren't drawn from a single origin point on the center of the node's right edge, but from corner to corner, etc..
I also tried Mermaid and ended up with surprisingly decent output using this code (link to the live editor):
---
config:
flowchart:
curve: step
---
graph LR
1[Start]
2[Intro]
3[Let me think...]
4[Choice]
5[Choice]
6[Choice]
7[Choice]
8[Choice]
1 --- 2
2 --- 3
3 --- 4
3 --- 5
3 --- 6
3 --- 7
3 --- 8
I could live with there being two other lines coming out the top and bottom of the node for multiple connections, but the extra ones beside them bother me; I'd rather they just continued up/down from the first lines before branching out again, if that makes any sense.
My question(s)
How can I achieve the precise visual graph structure I'm going for?
Is Graphviz, Mermaid, or some other library better suited for the task? Is there a way to do it using these tools that I somehow missed?

1 comment thread