Trees and taxa#

forestpd’s own tree and taxon types, as returned by forestpd.utils.prune() and held by a MaxMPDInstance (instance.trees, instance.registry). Most analyses never need them directly.

class forestpd.PhyloTree(n_nodes, n_leaves, edges, weight)[source]#

An unrooted, weighted phylogenetic tree.

The constructor stores its arguments as given and performs no validation; use from_edges() to build a tree from an arbitrary node numbering with checks.

Parameters:
  • n_nodes (int) – Number of nodes, including the leaves.

  • n_leaves (int) – Number of leaves; nodes 0..n_leaves-1 must be exactly the leaves.

  • edges (numpy.ndarray) – int32 array of shape (n_edges, 2) holding each edge’s two endpoints.

  • weight (numpy.ndarray) – float64 branch length per edge, aligned with edges.

Variables:
  • n_nodes (int) – Number of nodes. Nodes 0..n_leaves-1 are the leaves (leaf id == node id).

  • n_leaves (int) – Number of leaves.

  • edges (numpy.ndarray) – int32 array of shape (n_edges, 2) holding each edge’s two endpoints.

  • weight (numpy.ndarray) – float64 branch length per edge, aligned with edges.

Examples

>>> t = PhyloTree.from_edges(3, [(0, 2), (1, 2)], [1.0, 2.0], {0: 0, 1: 1})
>>> t.n_leaves, t.n_edges, t.total_weight()
(2, 2, 3.0)
property n_edges#

Number of edges.

classmethod from_edges(n_nodes, edges, weights, leaf_of_node)[source]#

Build a tree from an arbitrary node numbering, relabelling leaves to 0..n_leaves-1.

Parameters:
  • n_nodes (int) – Number of nodes in the input numbering (ids 0..n_nodes-1).

  • edges (Sequence[tuple[int, int]]) – Undirected edges as input-node pairs; must form a tree.

  • weights (Sequence[float]) – Branch length per edge, aligned with edges.

  • leaf_of_node (Mapping[int, int]) – Input node id -> leaf id. Leaf ids must be exactly 0..n_leaves-1.

Returns:

The tree, with leaves renumbered to their leaf ids and internal nodes numbered n_leaves..n_nodes-1 in input order.

Return type:

PhyloTree

Raises:

ForestPDInputError – If sizes mismatch, leaf ids are not contiguous, or the edges are not a tree.

classmethod from_leaf_arrays(n_nodes, edges, weights, leaf_nodes, leaf_ids)[source]#

from_edges() for edges already known to form a tree, from arrays.

Gives exactly the tree from_edges() would, without its connectivity search: the caller guarantees that the edges form a tree (a parsed tree does, by construction).

Parameters:
  • n_nodes (int) – Number of nodes in the input numbering.

  • edges (numpy.ndarray) – int[E, 2] input-node pairs forming a tree.

  • weights (numpy.ndarray) – float64[E] branch lengths.

  • leaf_nodes (numpy.ndarray) – int[L] input node id of each leaf.

  • leaf_ids (numpy.ndarray) – int[L] leaf id of each, a permutation of 0..L-1.

Returns:

The tree, numbered as by from_edges().

Return type:

PhyloTree

Raises:

ForestPDInputError – If sizes mismatch or the leaf ids are not exactly 0..L-1.

adjacency()[source]#

Return the adjacency in CSR form, computed once and cached.

Returns:

(start, to, via): the neighbours of node v are to[start[v]:start[v+1]], reached along edge indices via[start[v]:start[v+1]].

Return type:

tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

degrees()[source]#

Degree of every node.

Returns:

int32[n_nodes] array of node degrees.

Return type:

numpy.ndarray

neighbours(node)[source]#

The (neighbour, edge index) pairs at node.

Parameters:

node (int) – Node id.

Returns:

One (neighbour, edge index) pair per edge incident to node.

Return type:

list[tuple[int, int]]

root_at(root)[source]#

Root the tree at root (see RootedTree), caching the most recent rooting.

Parameters:

root (int) – Node id to root at.

Returns:

The rooting of this tree at root.

Return type:

RootedTree

total_weight()[source]#

Total branch length.

Returns:

Sum of all edge weights.

Return type:

float

class forestpd.TaxonRegistry(labels)[source]#

Bidirectional mapping between taxon labels and contiguous ids 0..n-1.

Ids follow sorted label order, so the mapping is deterministic across runs.

Parameters:

labels (Iterable[str]) – The taxon labels (duplicates and order ignored).

Examples

>>> reg = TaxonRegistry(["B", "A", "C"])
>>> reg.labels
('A', 'B', 'C')
>>> reg.id_of("B")
1
>>> sorted(reg.labels_of(  [0, 2]))
['A', 'C']
property labels#

Taxon labels, indexed by id.

property n#

Number of taxa.

id_of(label)[source]#

Integer id of label.

Parameters:

label (str) – A taxon label.

Returns:

The taxon’s id in 0..n-1.

Return type:

int

Raises:

ForestPDInputError – If label is not registered.

id_array(labels)[source]#

Ids of a sequence of labels, in order, as an array (one dictionary lookup in C).

Parameters:

labels (Sequence[str]) – Taxon labels.

Returns:

int64 id per label.

Return type:

numpy.ndarray

Raises:

ForestPDInputError – If a label is not registered (the first such label is named, as by id_of()).

Examples

>>> TaxonRegistry(["B", "A", "C"]).id_array(["C", "A"]).tolist()
[2, 0]
label_of(taxon_id)[source]#

Label of taxon_id.

Parameters:

taxon_id (int) – A taxon id in 0..n-1.

Returns:

The taxon’s label.

Return type:

str

ids_of(labels)[source]#

Ids of a set of labels.

Parameters:

labels (Iterable[str]) – Taxon labels.

Returns:

Their ids.

Return type:

set[int]

Raises:

ForestPDInputError – If any label is not registered.

labels_of(ids)[source]#

Labels of a set of ids.

Parameters:

ids (Iterable[int]) – Taxon ids in 0..n-1.

Returns:

Their labels.

Return type:

set[str]