Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions src/lineagetree/_basics/_navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,23 +360,20 @@ def nodes_at_t(
list of int
list of ids of the nodes at time `t` spawned by `r`
"""
if not r and r != 0:
r = {root for root in lT.roots if lT.time[root] <= t}
if r is None:
return lT.time_nodes.get(t, [])
if isinstance(r, int):
r = [r]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I guess one could do it that way at the beginning:

if r is None:
    ...

Instead of

if not r and r != 0:
    ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And yes, it would change the behavior since it would make the function return nothing in case the user gave [] for roots instead of returning the output of lT.roots which is I think a plus.
If the user specifically gave the empty list of nodes, it should not get any node in the return value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have time_nodes again, I don't care about the behaviour, so I will do that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually since we have the time_nodes the function should change entirely.

Copy link
Collaborator Author

@BadPrograms BadPrograms Aug 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think we might want to return a set and not a list. There is no reason to index the result, and I like sets more. The only reason to use a list is that the rest of the LineageTree consists mostly of lists, so we can do so for the sake of consistency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I guess one could do it that way at the beginning:

if r is None:
...

Instead of

if not r and r != 0:
...

Dont you want to do that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should the function change? and what should it be instead?

About the list vs set, the list can have an advantadge since it is explicitly ordered and that currently the nodes are returned in a specific order (preorder)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we dont provide roots it should return lT.time_nodes[t]

if t is None:
t = lT.t_e
to_do = list(r)
final_nodes = []
while len(to_do) > 0:
while 0 < len(to_do):
curr = to_do.pop()
for _next in lT._successor[curr]:
if lT._time[_next] < t:
to_do.append(_next)
elif lT._time[_next] == t:
final_nodes.append(_next)
if not final_nodes:
return list(r)
if lT._time[curr] == t:
final_nodes.append(curr)
elif lT._time[curr] < t:
to_do.extend(lT.successor[curr])
return final_nodes


Expand Down
Loading