2

I am trying to create a family tree using graphviz in python but have a problem with getting the persons on the same rank. In my example I'd like all the partners to be on the same rank for as much as possible. In this example Alice is alone highest up and then her children and partners come on the same rank below her. I'd like for her partners to end up next to her, I've tried setting rank = "same" and such but nothing seems to work.

The logic is probably not the best and there are certainly smoother ways to go about this but its in the first phase and I'd like to get it to work with the rank some how.

Below is my code so far,

from graphviz import Digraph

class Person:
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
        self.partners = []
        self.children = []

# Example family tree
alice = Person("Alice", "Female")
eddy = Person("Eddy", "Male")
bob = Person("Bob", "Male")
charlie = Person("Charlie", "Male")
dave = Person("Dave", "Male")
eve = Person("Eve", "Female")
frank = Person("Frank", "Male")
fp = Person("fictional Partner", "Female")
fjr = Person("fjr", "Female")
fjr2 = Person("fjr2", "Male")

alice.partners.append(eddy)
alice.children.append(bob)
alice.children.append(charlie)
eddy.children.append(dave)
eddy.children.append(eve)
eddy.children.append(frank)
alice.partners.append(fp)
frank.children.append(fjr)
frank.children.append(fjr2)

def build_family_tree(person, graph):
    # Add the current person to the graph
    graph.node(person.name, shape="none", label=person.name)

    # Recursively traverse the children and add them to the graph
    for child in person.children:
        graph.edge(person.name, child.name, arrowhead="none")
        build_family_tree(child, graph)

    # Recursively traverse the partners and their children
    for partner in person.partners:
        graph.node(partner.name, shape="none", label=partner.name)
        graph.edge(person.name, partner.name, style="dashed")
        for child in partner.children:
            graph.edge(partner.name, child.name, arrowhead="none")
            build_family_tree(child, graph)

# Create a new graph
family_tree_graph = Digraph()

# Build the family tree starting from Alice
build_family_tree(alice, family_tree_graph)

# Render the graph to a file
family_tree_graph.render('family_tree', format='png', view=True)

The family tree with the partners on the wrong rank

Jahlove
  • 65
  • 9
  • 1
    Rank=same is not a node attribute or a Root attribute, but a subgraph attribute. For each desired "partner" rank, you need to create a subgraph and give the subgraph an attribute of "rank=same". – sroush Jun 20 '23 at 14:39
  • That did it, thank you sroush! – Jahlove Jun 21 '23 at 12:27

1 Answers1

0

From sroush's comment:

The attribute rank is a subgraph attribute. The nodes needs to be put together in a subgraph with said attribute.

In your case, right after adding the partner's edge, you can add:

with graph.subgraph() as sub:                                           
  sub.attr(rank="same")                                               
  sub.node(person.name)                                               
  sub.node(partner.name)