Partners on same rank in family tree using Python and Graphviz

94 Views Asked by At

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

1

There are 1 best solutions below

0
Yuni Tsukiyama On

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)