Skip to content

Commit 8a69970

Browse files
hyanwongmergify[bot]
authored andcommitted
Make the returned rank a namedtuple
1 parent 812af67 commit 8a69970

File tree

5 files changed

+41
-9
lines changed

5 files changed

+41
-9
lines changed

docs/python-api.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,13 @@ Also see the {ref}`sec_python_api_tree_sequences` summary.
12481248
```{eval-rst}
12491249
.. autoclass:: Interval()
12501250
:members:
1251+
```
1252+
1253+
#### The {class}`Rank` class
12511254

1255+
```{eval-rst}
1256+
.. autoclass:: Rank()
1257+
:members:
12521258
```
12531259

12541260
### TableCollection and Table classes

python/tests/test_combinatorics.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#
22
# MIT License
33
#
4-
# Copyright (c) 2020-2021 Tskit Developers
4+
# Copyright (c) 2020-2022 Tskit Developers
55
#
66
# Permission is hereby granted, free of charge, to any person obtaining a copy
77
# of this software and associated documentation files (the "Software"), to deal
@@ -37,6 +37,7 @@
3737
import tskit
3838
import tskit.combinatorics as comb
3939
from tests import test_stats
40+
from tskit.combinatorics import Rank
4041
from tskit.combinatorics import RankTree
4142

4243

@@ -220,7 +221,7 @@ def test_unrank_labelled(self, n):
220221
@pytest.mark.parametrize("n", range(10))
221222
def test_unrank_unlabelled(self, n):
222223
for shape_rank in range(comb.num_shapes(n)):
223-
rank = (shape_rank, 0)
224+
rank = Rank(shape_rank, 0)
224225
unranked = RankTree.unrank(n, rank)
225226
assert rank, unranked.rank()
226227

@@ -288,6 +289,15 @@ def test_label_unrank(self, n):
288289
assert labelled_tree.rank() == rank
289290
assert unranked.rank() == rank
290291

292+
def test_rank_names(self):
293+
shape = 1
294+
label = 0
295+
n = 3
296+
tree = tskit.Tree.unrank(n, (shape, label))
297+
rank = tree.rank()
298+
assert rank.shape == shape
299+
assert rank.label == label
300+
291301
@pytest.mark.parametrize("n", range(6))
292302
def test_unrank_rank_round_trip(self, n):
293303
for shape_rank in range(comb.num_shapes(n)):

python/tskit/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
all_tree_shapes,
8484
all_tree_labellings,
8585
TopologyCounter,
86+
Rank,
8687
)
8788
from tskit.drawing import SVGString # NOQA
8889
from tskit.exceptions import * # NOQA

python/tskit/combinatorics.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,31 @@
3030
import itertools
3131
import json
3232
import random
33+
from typing import NamedTuple
3334

3435
import attr
3536
import numpy as np
3637

3738
import tskit
3839

3940

41+
class Rank(NamedTuple):
42+
"""
43+
A tuple of 2 numbers, ``(shape, label)``, together defining a unique
44+
topology for a labeled tree. See :ref:`sec_combinatorics`.
45+
"""
46+
47+
shape: int
48+
"""
49+
A non-negative integer representing the (unlabelled) topology of a tree with a
50+
defined number of tips.
51+
"""
52+
label: int
53+
"""
54+
A non-negative integer representing the order of labels for a given tree topology.
55+
"""
56+
57+
4058
def equal_chunks(lst, k):
4159
"""
4260
Yield k successive equally sized chunks from lst of size n.
@@ -796,7 +814,7 @@ def num_labellings(self):
796814
return num_list_of_group_labellings(child_groups)
797815

798816
def rank(self):
799-
return self.shape_rank(), self.label_rank()
817+
return Rank(self.shape_rank(), self.label_rank())
800818

801819
def shape_rank(self):
802820
if self._shape_rank is None:

python/tskit/trees.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -849,19 +849,18 @@ def seek(self, position):
849849
raise ValueError("Position out of bounds")
850850
self._ll_tree.seek(position)
851851

852-
def rank(self):
852+
def rank(self) -> tskit.Rank:
853853
"""
854854
Produce the rank of this tree in the enumeration of all leaf-labelled
855855
trees of n leaves. See the :ref:`sec_tree_ranks` section for
856856
details on ranking and unranking trees.
857857
858-
:rtype: tuple(int)
859858
:raises ValueError: If the tree has multiple roots.
860859
"""
861860
return combinatorics.RankTree.from_tsk_tree(self).rank()
862861

863862
@staticmethod
864-
def unrank(num_leaves, rank, *, span=1, branch_length=1):
863+
def unrank(num_leaves, rank, *, span=1, branch_length=1) -> Tree:
865864
"""
866865
Reconstruct the tree of the given ``rank``
867866
(see :meth:`tskit.Tree.rank`) with ``num_leaves`` leaves.
@@ -880,14 +879,13 @@ def unrank(num_leaves, rank, *, span=1, branch_length=1):
880879
from which the tree is taken will have its
881880
:attr:`~tskit.TreeSequence.sequence_length` equal to ``span``.
882881
:param: float branch_length: The minimum length of a branch in this tree.
883-
:rtype: Tree
884882
:raises: ValueError: If the given rank is out of bounds for trees
885883
with ``num_leaves`` leaves.
886884
"""
887885
rank_tree = combinatorics.RankTree.unrank(num_leaves, rank)
888886
return rank_tree.to_tsk_tree(span=span, branch_length=branch_length)
889887

890-
def count_topologies(self, sample_sets=None):
888+
def count_topologies(self, sample_sets=None) -> tskit.TopologyCounter:
891889
"""
892890
Calculates the distribution of embedded topologies for every combination
893891
of the sample sets in ``sample_sets``. ``sample_sets`` defaults to all
@@ -926,7 +924,6 @@ def count_topologies(self, sample_sets=None):
926924
:param list sample_sets: A list of lists of Node IDs, specifying the
927925
groups of nodes to compute the statistic with.
928926
Defaults to all samples grouped by population.
929-
:rtype: tskit.TopologyCounter
930927
:raises ValueError: If nodes in ``sample_sets`` are invalid or are
931928
internal samples.
932929
"""

0 commit comments

Comments
 (0)