tskit icon indicating copy to clipboard operation
tskit copied to clipboard

Tree.ancestors(u) method

Open hyanwong opened this issue 2 years ago • 2 comments

As I've been implementing tree traversal methods, I've commonly wanted to go up the chain of parents for a node. I think there's a good argument for a tree.parents(u) (or tree.ancestors?) method which returns an iterator which then stops when the root is reached. This is a pretty fundamental tree operation and handy to avoid messing with all that tskit.NULL stuff for newbies:

def parents(self, u):
    while self.parent(u) != tskit.NULL:
        u = self.parent(u)
        yield u

Thoughts? Worth the extra API burden?

hyanwong avatar Feb 04 '23 16:02 hyanwong

We started implementing something similar in #2350, which was Tree.path(u, v=None) which returned the path to root when provided with a single node.

I think parents is a bit to easy to get mixed up with parent.

Tree.ancestors(u) is good choice I think, but we need to be careful with the implementation. This seems reasonable?

def ancestors(self, u):
    """
    Returns an iterator over the ancestors of u in this tree.
    """
    u = self.parent(u)
    while u != -1:
         yield u
         u = self.parent(u)

Arguably it would be more useful/efficient to return a list or an array of the nodes, but I think it's probably best to be consistent with the nodes() function here by returning an iterator.

jeromekelleher avatar Feb 06 '23 09:02 jeromekelleher

Similar function defined here

jeromekelleher avatar Feb 06 '23 09:02 jeromekelleher