API Reference
EvoTen: Vectorized, differentiable computation of tree likelihoods supporting different computation backends.
This page provides a complete reference to all public classes, functions, and modules in EvoTen.
Core Module
The main evoten module exports the primary classes and functions.
Model
- evoten.model.PRUNING_MODES = ('routed', 'buffer')
The schedules of compute_ancestral_probabilities (argument pruning).
- evoten.model.compute_ancestral_marginals(leaves, tree_handler, transition_probs, equilibrium_logits, leaf_names=None, leaves_are_probabilities=True, return_probabilities=False, return_upward_messages=False, return_downward_messages=False)[source]
Compute all marginal distributions at internal (ancestral) nodes u in the given leaf data and the tree. Formally, the method computes sP(u | leaves, tree) for all u that are not leaves.
Broadcasting is supported for this dimension.
- Parameters:
leaves – Logits of all symbols at all leaves of shape (num_leaves, models*, L, d).
tree_handler (TreeHandler) – TreeHandler object
transition_probs – Probabilistic transition matrices of shape (num_nodes-1, models, L*, d, d).
equilibrium_logits – Equilibrium distribution logits of shape (models, d).
leaf_names – Names of the leaves (list-like of length num_leaves). Used to reorder correctly.
leaves_are_probabilities – If True, leaves are assumed to be probabilities or one-hot encoded.
return_probabilities – If True, return probabilities instead of logliks.
return_upward_messages – If True, also returns upward messages of shape (num_nodes-1, models).
return_downward_messages – If True, also returns downward messages of shape (num_nodes-1, models).
- Returns:
Ancestral marginals of shape (num_ancestral_nodes, models, L, d).
- evoten.model.compute_ancestral_probabilities(leaves, tree_handler, transition_probs, leaf_names=None, return_only_root=False, leaves_are_probabilities=True, return_probabilities=False, pruning='routed')[source]
Computes all (partial) log-likelihoods at all internal (ancestral) nodes u in the given tree, that is P(leaves below u | u, tree) for all u that are not leaves. Supports multiple, parallel models. Uses a vectorized implementation of Felsenstein’s pruning algorithm that treats models, sequence positions and all nodes within a tree layer in parallel.
Broadcasting is supported for this dimension.
- Parameters:
leaves – Logits of all symbols at all leaves of shape (num_leaves, models*, L, d).
tree_handler (TreeHandler) – TreeHandler object
transition_probs – Probabilistic transition matrices of shape (num_nodes-1, models, L*, d, d) or (num_nodes-1, models, d, d).
leaf_names – Names of the leaves (list-like of length num_leaves). Used to reorder correctly.
return_only_root – If True, only the root node logliks are returned.
leaves_are_probabilities – If True, leaves are assumed to be probabilities or one-hot encoded.
return_probabilities – If True, return probabilities instead of logliks.
pruning – How the layers are combined; both give the same result. “routed” (default): each height layer accumulates in its own tensor, fed through a static routing; out of place and capturable by torch.compile; faster for large d * L, especially on deep trees. “buffer”: every layer’s messages are added into one (num_ancestral_nodes, models, L, d) buffer; fewer, larger operations, faster for small d * L.
- Returns:
Ancestral logliks of shape (models, L, d) if return_only_root else shape (num_ancestral_nodes, models, L, d)
- evoten.model.compute_leaf_out_marginals(leaves, tree_handler, transition_probs, equilibrium_logits, leaf_names=None, leaves_are_probabilities=True, return_probabilities=False)[source]
Computes the marginal distributions of the leaves given all other leaves, the tree topology and the rate matrix. Formally, the method computes P(u | leaves_except_u, tree, rates) for all leaves u.
Broadcasting is supported for this dimension.
- Parameters:
leaves – Logits of all symbols at all leaves of shape (num_leaves, models*, L, d).
tree_handler (TreeHandler) – TreeHandler object
transition_probs – Probabilistic transition matrices of shape (num_nodes-1, models, L*, d, d).
equilibrium_logits – Equilibrium distribution logits of shape (models, d).
leaf_names – Names of the leaves (list-like of length num_leaves). Used to reorder correctly.
leaves_are_probabilities – If True, leaves are assumed to be probabilities or one-hot encoded.
return_probabilities – If True, return probabilities instead of logliks.
- Returns:
Leaf-out marginals of shape (num_leaves, models, L, d).
- evoten.model.loglik(leaves, tree_handler, transition_probs, equilibrium_logits, leaf_names=None, leaves_are_probabilities=True, pruning='routed')[source]
Computes log P(leaves | tree, rate_matrix).
Broadcasting is supported for this dimension.
- Parameters:
leaves – Logits of all symbols at all leaves of shape (num_leaves, models*, L, d).
tree_handler (TreeHandler) – TreeHandler object
transition_probs – Probabilistic transition matrices of shape (num_nodes-1, models, L*, d, d) or (num_nodes-1, models, d, d).
equilibrium_logits – Equilibrium distribution logits of shape (models, L*, d).
leaf_names – Names of the leaves (list-like of length num_leaves). Used to reorder correctly.
leaves_are_probabilities – If True, leaves are assumed to be probabilities or one-hot encoded.
pruning – “routed” (default) or “buffer”, see compute_ancestral_probabilities.
- Returns:
Log-likelihoods of shape (models, L).
- evoten.model.propagate(root, tree_handler, transition_probs)[source]
Propagates a root distribution along the tree topology. The method computes P(u | root, tree) for all nodes u in the tree.
Broadcasting is supported for this dimension.
- Parameters:
root – Probabilities of all symbols at the root node of shape (1, models*, L, d).
tree_handler (TreeHandler) – TreeHandler object
transition_probs – Probabilistic transition matrices of shape (num_nodes-1, models, L*, d, d).
Tree Handler
- class evoten.tree_handler.NodeData(node: Bio.Phylo.BaseTree.Clade, parent: Bio.Phylo.BaseTree.Clade, height: int = -1, index: int = -1, finished: bool = False)[source]
Bases:
object- Parameters:
node (Clade)
parent (Clade)
height (int)
index (int)
finished (bool)
- finished: bool = False
- height: int = -1
- index: int = -1
- node: Clade
- parent: Clade
- class evoten.tree_handler.TreeHandler(tree=None, root_name=None)[source]
Bases:
objectWraps a rooted tree and provides utility functions useful for a height-wise processing of the tree.
- Parameters:
tree (<module 'Bio.Phylo.BaseTree' from '/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/Bio/Phylo/BaseTree.py'>) – Bio.Phylo tree object that will we wrapped by this class. If None, a tree with only a root node will be created.
root_name – Name of the root node when creating a new tree.
- change_root(new_root_name)[source]
- Rotates the tree such that a different node becomes the root.
Calls update() automatically.
- Parameters:
new_root_name – Name of the new root node, can be any internal node
tree. (in the)
- collapse(node_name)[source]
Collapses a node in the tree. Call update() after all tree modifications are done.
- classmethod copy(tree_handler)[source]
Copies another tree handler.
- Parameters:
tree_handler – TreeHandler object to copy.
- device_index(name, values, like)[source]
An index vector as the backend’s native integer tensor, placed where
likelives and cached per (name, device).The tree’s index arrays (leaf permutation, per-layer stratum ids, level routing) are numpy and static. Converting them inside the per-column computation would add a host-to-device copy per use and makes
torch.compiletreat them as data-dependent; converting once and caching them keeps the traced computation free of numpy.- Parameters:
name – Hashable key identifying the array (e.g.
("perm", ...)).values – The numpy index array (only used on a cache miss).
like – A tensor whose backend device the index should live on.
- classmethod from_newick(newick_str)[source]
Reads a tree from a newick string.
- Parameters:
filename – handle or filepath
fmt – Format of the tree file. Supports all formats supported by Bio.Phylo.
- get_branch_lengths_by_height(height)[source]
Retrieves a vector with the branch lengths for each node with the given height.
- Parameters:
height – Height of the subtree rooted at a node.
- get_internal_counts_by_height(height)[source]
Retrieves a vector with the number of child nodes that are internal for each node in the given layer.
Example: For the tree ROOT / | A B C |\ | /|D E F G H I | | | x y z and height=2, the function will return [1,2].
- Parameters:
height – Height of the subtree rooted at a node.
- get_leaf_counts_by_height(height)[source]
Retrieves a vector with the number of child nodes that are leafs for each node in the given layer.
Example: For the tree ROOT / | A B C |\ | /|D E F G H I | | | x y z and height=1, the function will return [1, 1, 1, 1].
- Parameters:
height – Height of the subtree rooted at a node.
- get_parent_indices_by_height(height)[source]
Retrieves a vector with the index of the parent for each node in a height layer.
- get_values_by_height(kernel, height, leaves_included=True, indexes_branches=False)[source]
Retrieves all values from the leftmost axis of a tensor corresponding to all nodes with a given height.
- Parameters:
kernel – A tensor of shape (num_nodes-1, …) or (num_nodes, …) (root last; might be excluded),
and (representing all branch lengths ordered by tree height) – left-to-right (starting with leaves).
height – Height of the subtree rooted at a node.
leaves_included – If False, the method will assume a kernel if shape (num_nodes-num_leaves, …) and height=0 is invalid.
indexes_branches – If True, the kernel has one entry per branch (edge), e.g. branch lengths or transition probabilities. This enables the stratified fast path when the tree is stratified: a compact kernel of shape (num_strata, …) is gathered via branch_to_stratum instead of sliced directly. Must be False for node-indexed kernels (e.g. anc_logliks).
- Returns:
Tensor of shape (layer_size, …) representing the branch lengths for the tree layer.
- level_routing()[source]
Static routing of upward messages between height layers.
Returns a list over child heights
h = 0 .. height-1; entryhis a list of groups(parent_height, src, dst, src_is_identity, dst_is_identity)with numpy int64 index vectors: the nodessrc(positions within layerh) have their parents at heightparent_heightat positionsdst(within that layer). Groups are sorted byparent_height; every node of layerhoccurs in exactly one group.src_is_identitysayssrc == arange(layer size)(no gather needed);dst_is_identitysays the group maps layerhone-to-one onto the whole parent layer (no aggregation needed). Cached; recomputed byupdate().
- prune()[source]
Prunes the tree by removing all leaves, i.e. strips the lowest height layer.
Call update() after all tree modifications are done.
- classmethod read(file, fmt='newick')[source]
Reads a tree from a file.
- Parameters:
filename – handle or filepath
fmt – Format of the tree file. Supports all formats supported by Bio.Phylo.
- reorder(tensor, node_names, axis=0)[source]
- Reorders the tensor along the given axis to be sorted in a way
compatible with the tree. This method is meant to be statically compiled in the compute graph (leaf order is always the same).
- Parameters:
tensor – A tensor of shape (…, k, …).
node_names – List-like of k node names in the order as they appear in the tensor.
axis – The axis along which the tensor should be reordered.
- routing_for(like)[source]
level_routing()with the index vectors converted once to the backend’s native tensors on the device oflike(cached per device, seedevice_index()).
- set_branch_lengths(branch_lengths, update_phylo_tree=True)[source]
Sets the branch lengths of the tree.
- Parameters:
branch_lengths –
A tensor of shape (num_nodes-1, k) representing the branch lengths of each node to its parent.
k is the number of models
- split(node_name, n=2, branch_length=1.0, names=None)[source]
Generates n new descendants for a node. Call update() after all tree modifications are done.
- stratify_branchlen(max_num_explicit_blen)[source]
Partitions branch lengths into quantile strata to reduce computation.
After calling this, make_transition_probs can be called with strata_blen_values (shape (K, 1)) instead of the full branch_lengths (shape (num_nodes-1, 1)). get_values_by_height then automatically gathers the correct rows for each height layer from the compact tensor.
Has no effect (sets is_stratified=False) when max_num_explicit_blen >= num_nodes-1, i.e. when no reduction is possible.
This method should only be called when branch lengths are fixed (not subject to optimisation), because stratification bakes in the current branch lengths.
- Parameters:
max_num_explicit_blen – Maximum number of distinct representative branch-length values to use. Must be a positive integer.
Substitution Models
- evoten.substitution_models.AF_3Di(alphabet='ACDEFGHIKLMNPQRSTVWY', dtype=<class 'numpy.float32'>)[source]
Returns the exchangeabilities and equilibrium frequencies for a for 3Di characters derived from AlphaFold structures.
Hochberg, Georg, 2025, “A general substitution matrix for structural phylogenetics.”, https://doi.org/10.17617/3.1MJJBH, Edmond, V3
- Parameters:
alphabet (str) – A string with the amino acids in the desired order.
dtype (type[floating]) – The desired dtype for the returned arrays.
- Returns:
symmetric d x d tensor of exchangeabilities and d vector of equilibrium frequencies.
- Return type:
tuple[ndarray, ndarray]
- evoten.substitution_models.LG(alphabet='ARNDCQEGHILKMFPSTWYV', dtype=<class 'numpy.float32'>)[source]
- Returns the exchangeabilities and equilibrium frequencies for the LG
model. Si Quang Le, Olivier Gascuel An Improved General Amino Acid Replacement Matrix, 2008 Use for amino acids.
- Parameters:
alphabet (str) – A string with the amino acids in the desired order.
dtype (type[floating]) – The desired dtype for the returned arrays.
- Returns:
symmetric d x d tensor of exchangeabilities and d vector of equilibrium frequencies.
- Return type:
tuple[ndarray, ndarray]
- evoten.substitution_models.codon_frequencies(nuc_freqs=None, stop_freq=1e-06, code='standard', dtype=<class 'numpy.float64'>)[source]
Returns equilibrium frequencies of the 64 codons.
The sense codons get the total frequency 1 - stop_freq, distributed uniformly (nuc_freqs None) or proportionally to the product of nucleotide frequencies (F1x4 for shape (4,), F3x4 for shape (3, 4) with one row per codon position). The stop codons share stop_freq equally. A positive stop_freq keeps all frequencies positive, as required by reversible transition matrices (expm_torch.expm_gtr) and softmax parameterizations.
- Parameters:
nuc_freqs (ndarray | Sequence | None) – None or nucleotide frequencies (a, c, g, t) of shape (4,) or (3, 4).
stop_freq (float) – Total frequency of the stop codons, in (0, 1).
code (str) – Genetic code, see genetic_code.
dtype (type[floating])
- Returns:
Array of shape (64,) in the order of util.tuple_labels(3).
- Return type:
ndarray
- evoten.substitution_models.foldseek_3Di(alphabet='ACDEFGHIKLMNPQRSTVWY', dtype=<class 'numpy.float32'>)[source]
Returns the exchangeabilities and equilibrium frequencies for a model derived from Foldseek’s 3Di substitution matrix.
Based on https://github.com/steineggerlab/foldseek/blob/master/data/mat3di.out See docs/misc/3Di_Q_from_P.ipynb for construction details.
- Parameters:
alphabet (str) – A string with the amino acids in the desired order.
dtype (type[floating]) – The desired dtype for the returned arrays.
- Returns:
symmetric d x d tensor of exchangeabilities and d vector of equilibrium frequencies.
- Return type:
tuple[ndarray, ndarray]
- evoten.substitution_models.genetic_code(name='standard')[source]
Returns the amino acid encoded by each of the 64 codons.
- Parameters:
name (str) – Name of the genetic code. Only “standard” (NCBI translation table 1) is supported.
- Returns:
Array of shape (64,) with one-letter amino acid codes in the order of util.tuple_labels(3); stop codons are ‘*’.
- Return type:
ndarray
- evoten.substitution_models.gy94(kappa=4.0, omega=1.0, codon_freqs=None, *, min_exchangeability=0.001, code='standard', dtype=<class 'numpy.float64'>)[source]
Returns the exchangeabilities and equilibrium frequencies of a codon model in the style of Goldman and Yang (1994) on all 64 triplets.
Two codons that differ at one position have the exchangeability kappa^[transition] * omega^[different amino acids]; stop codons count as an amino acid of their own. With Q_ij = R_ij * pi_j (see Backend.make_rate_matrix) this is the GY94 rate matrix. Unlike in GY94, every off-diagonal exchangeability is at least a small floor, which applies in particular to codons that differ at 2 or 3 positions. The exchangeabilities are thus strictly positive, e.g. representable as the softplus of a kernel.
- Parameters:
kappa (float) – Transition/transversion ratio.
omega (float) – Nonsynonymous/synonymous rate ratio (dN/dS).
codon_freqs (ndarray | Sequence[float] | None) – Equilibrium frequencies of shape (64,), default codon_frequencies() (uniform sense codons, rare stop codons).
min_exchangeability (float) – Floor relative to the mean exchangeability of the codon pairs that differ at one position; 0 disables it.
code (str) – Genetic code, see genetic_code.
dtype (type[floating])
- Returns:
Symmetric 64 x 64 exchangeabilities with zero diagonal (not normalized) and 64 equilibrium frequencies, in the order of util.tuple_labels(3).
- Return type:
tuple[ndarray, ndarray]
- evoten.substitution_models.jukes_cantor(mue=1.3333333333333333, d=4, dtype=<class 'numpy.float32'>)[source]
Returns the exchangeabilities and equilibrium frequencies for the Jukes-Cantor model.
- Parameters:
mue (float | Sequence[float]) – Scalar, list or 1D array.
d (int)
dtype (type[floating])
- Returns:
- symmetric k x d x d tensor of exchangeabilities and k x d matrix of
equilibrium frequencies.
k is the length of mue or 1 if mue is a scalar.
- Return type:
tuple[ndarray, ndarray]
- evoten.substitution_models.mean_rate(R, pi)[source]
Returns the expected substitution rate sum_i pi_i sum_j R_ij pi_j of the unnormalized rate matrix Q_ij = R_ij * pi_j (R with zero diagonal), i.e. the normalizing factor of Backend.make_rate_matrix.
- Parameters:
R (ndarray) – Exchangeabilities of shape (…, d, d).
pi (ndarray) – Equilibrium frequencies of shape (…, d).
- Returns:
Array of shape (…).
- Return type:
ndarray
- evoten.substitution_models.nucleotide_gtr(rates=None, kappa=None, freqs=(0.25, 0.25, 0.25, 0.25), dtype=<class 'numpy.float64'>)[source]
Returns the exchangeabilities and equilibrium frequencies of a nucleotide model (order a, c, g, t).
- Parameters:
rates (Sequence[float] | None) – The six exchangeabilities (ac, ag, at, cg, ct, gt) of a GTR model.
kappa (float | None) – Transition/transversion ratio of an HKY model, i.e. the exchangeability of a<->g and c<->t while all others are 1. If neither rates nor kappa is given, all exchangeabilities are 1.
freqs (Sequence[float]) – Equilibrium frequencies, normalized to sum to 1.
dtype (type[floating])
- Returns:
Symmetric 4 x 4 exchangeabilities with zero diagonal and the 4 equilibrium frequencies.
- Return type:
tuple[ndarray, ndarray]
- evoten.substitution_models.triplet_independent(nuc_models, *, min_exchangeability=0.001, dtype=<class 'numpy.float64'>)[source]
Returns the exchangeabilities and equilibrium frequencies of a 64-state triplet model in which the three nucleotides evolve independently, e.g. a model of non-coding sequence on the state space of a codon model.
Position p evolves under the nucleotide rate matrix Q_p of (R_p, pi_p), normalized to one expected substitution per time unit. The triplet rate matrix is the Kronecker sum Q = Q_1 x I x I + I x Q_2 x I + I x I x Q_3 (three expected substitutions per time unit) with the equilibrium pi_1 x pi_2 x pi_3. Q is reversible and R_ij = Q_ij / pi_j. As in gy94, the off-diagonal exchangeabilities are raised to a floor.
- Parameters:
nuc_models – One nucleotide model (R, pi) with shapes (4, 4) and (4,) for all positions or a sequence of three, e.g. from nucleotide_gtr.
min_exchangeability (float) – Floor relative to the mean exchangeability of the triplet pairs that differ at one position; 0 disables it.
dtype (type[floating])
- Returns:
Symmetric 64 x 64 exchangeabilities with zero diagonal and 64 equilibrium frequencies, in the order of util.tuple_labels(3).
- Return type:
tuple[ndarray, ndarray]
Utilities
- evoten.util.data_path(filename)[source]
Yields a real filesystem path to a data file.
- Parameters:
filename (str)
- Return type:
Iterator[Path]
- evoten.util.encode_one_hot(sequences, alphabet)[source]
One-hot encodes a list of strings over the given alphabet.
- Parameters:
sequences (Sequence[str])
alphabet (str)
- Return type:
ndarray
- evoten.util.encode_tuple_alignment(ta, k=3, gap_symbols='-', gap_separate_state=0)[source]
One-hot encode a tuple alignment produced by tuple_alignment().
Each k-character entry is converted to a base-4 integer index (a=0, c=1, g=2, t=3), so ‘aaa’->0 and ‘cgt’->1*16+2*4+3=27. Gap entries and entries containing characters outside {a,c,g,t,A,C,G,T} are encoded as all-ones (unknown/missing) unless gap_separate_state >= 1, in which case gap entries are one-hot at index 4**k.
- Parameters:
ta (List[str]) – Output of tuple_alignment(); R strings each of length L*k.
k (int) – Tuple length used to produce ta (default 3).
gap_symbols (str) – Characters treated as gaps (default ‘-‘).
gap_separate_state (int) – Number of extra gap states appended to the alphabet (default 0). If >= 1, gap entries are one-hot at index 4**k instead of all-ones.
- Returns:
- Shape [R, L, 4**k + gap_separate_state], dtype float32.
Valid k-mer entries are one-hot. Ambiguous entries are all-ones. Gap entries are all-ones when gap_separate_state=0, or one-hot at index 4**k when gap_separate_state >= 1.
- Return type:
np.ndarray
- evoten.util.parse_rate_model(path)[source]
Parses a rate model from a file. The first row is expected to contain the equilibrium frequencies, and the remaining rows are expected to contain the exchangeabilities (lower triangular matrix without diagonal). After the matrix, an optional scaling factor can be provided in a separate line.
The file can contain comments starting with ‘#’.
- Parameters:
path (Path | str) – Path to the rate model file.
- Returns:
A tuple
(exchangeabilities, equilibrium frequencies, scaling factor)with shapes(n, n),(n,)and a scalar respectively. When the scaling factor is not provided, it defaults to 1.- Return type:
tuple[ndarray, ndarray, float]
- evoten.util.permute_rate_model(exchangeabilities, equilibrium, alphabet, new_alphabet)[source]
Permutes a rate model to match a new alphabet. The new alphabet must be a permutation of the old alphabet.
- Parameters:
exchangeabilities (ndarray) – Exchangeability matrix of shape (n, n).
equilibrium (ndarray) – Equilibrium frequencies of shape (n,).
alphabet (str) – Original alphabet.
new_alphabet (str) – New alphabet.
- Returns:
A tuple
(new_exchangeabilities, new_equilibrium)with the same shapes as the input exchangeabilities and equilibrium, but permuted to match the new alphabet.- Return type:
tuple[ndarray, ndarray]
- evoten.util.print_tuple_rate_matrix(Q, k, label=None, file=None)[source]
Pretty-print a rate matrix with k-mer row/column labels.
- Parameters:
Q (ndarray) – 2-D array-like of shape (4**k, 4**k).
k (int) – Tuple size used to produce Q.
label (str) – Optional header line printed before the matrix.
file (IO[str] | None) – File object for output (default: sys.stdout).
- Return type:
None
- evoten.util.print_tuple_stationary(pi, k, label=None, file=None)[source]
Pretty-print a stationary distribution with k-mer labels.
- Parameters:
pi (ndarray) – 1-D array-like of shape (4**k,).
k (int) – Tuple size.
label (str) – Optional header line printed before the values.
file (IO[str] | None) – File object for output (default: sys.stdout).
- Return type:
None
- evoten.util.tuple_alignment(sequences, k=3, gap_symbols='-')[source]
Construct a tuple alignment from a multiple sequence alignment (MSA).
For each row, k-mers of k consecutive non-gap characters are identified by their column-index tuple (c_0, …, c_{k-1}). Output columns are the equivalence classes — unique column-index tuples — that appear in at least two rows, sorted lexicographically. Each output entry is either the k characters at those columns or k gap characters.
For a gap-less MSA with L columns the output has L-k+1 columns.
- Parameters:
sequences (List[str]) – MSA rows, all the same length.
k (int) – Tuple length; k=3 gives codon-level alignment.
gap_symbols (str) – Characters treated as gaps. The first character is used to fill missing entries in the output.
- Returns:
One string per row; length = (number of output columns) * k.
- Return type:
List[str]
Example
S = [‘ACGT’, ‘A-GT’, ‘ACG-‘] tuple_alignment(S, k=2) # => [‘ACCGGT’, ‘—-GT’, ‘ACCG–‘] # Column-index tuples with count>=2: (0,1), (1,2), (2,3) # Row 1 lacks (0,1) and (1,2); row 2 lacks (2,3).
- evoten.util.tuple_array(sequences, k=3, gap_symbols='-', gap_separate_state=0, gap_class=None, return_index_tuples=False)[source]
Directly compute the one-hot encoded tuple alignment array.
Combines tuple_alignment() and encode_tuple_alignment() in a single pass, avoiding intermediate string allocation. Equivalent to:
- encode_tuple_alignment(tuple_alignment(sequences, k, gap_symbols),
k, gap_symbols, gap_separate_state)
For each row, non-gap positions are found and k-tuples of consecutive positions are mapped to base-4 indices. Valid tuples (present in >=2 rows) are written as one-hot vectors into the output array using batch numpy indexing.
With gap_separate_state=0 (default): absent/gap entries are all-ones (neutral for Felsenstein’s pruning algorithm). With gap_separate_state=1: absent entries are one-hot at index 4**k (explicit gap state); ambiguous entries remain all-ones. With gap_separate_state=2: two gap states — gap_short at index 4**k, gap_long at 4**k+1. gap_class (if not None) distinguishes them; absent entries default to gap_long.
- Parameters:
sequences (List[str]) – MSA rows, all the same length.
k (int) – Tuple length; k=3 for codons.
gap_symbols (str) – Characters treated as gaps (default ‘-‘).
gap_separate_state (int) – Extra gap states appended to the alphabet (default 0).
gap_class (np.ndarray or None) – Integer array of shape (R, n_cols), dtype int8. Values: 0=nucleotide, 1=gap_short, 2=gap_long/absent. Used only when gap_separate_state == 2.
return_index_tuples (bool) – If True, also return the index tuples.
- Returns:
np.ndarray, shape [R, L, 4**k + gap_separate_state], float32. first_positions : np.ndarray, shape [L], dtype int64.
For each output column j, the 0-based alignment column index of the first character of tuple j.
- index_tuplesnp.ndarray, shape [L, k], dtype int64 (only with
return_index_tuples). Row j holds the k 0-based alignment column indices of tuple j (sorted lexicographically over j, so index_tuples[:, 0] == first_positions).
- Return type:
result
- evoten.util.tuple_labels(k)[source]
Return the list of 4**k k-mer strings in base-4 index order.
Index i corresponds to the k-mer whose base-4 digits (most-significant first) give bases _INT_TO_BASE[digit]. E.g. for k=2: index 0 → ‘aa’, index 1 → ‘ac’, index 4 → ‘ca’, index 15 → ‘tt’.
- Parameters:
k (int) – Tuple length.
- Returns:
4**k strings of length k.
- Return type:
List[str]
- evoten.util.write_rate_model(path, exchangeabilities, equilibrium, scaling_factor=1.0)[source]
Writes a rate model to a file. The first row contains the equilibrium frequencies, and the remaining rows contain the exchangeabilities (lower triangular matrix without diagonal). An optional scaling factor can be provided in a separate line after the matrix.
- Parameters:
exchangeabilities (ndarray) – Exchangeability matrix of shape (n, n).
equilibrium (ndarray) – Equilibrium frequencies of shape (n,).
scaling_factor (float) – Optional scaling factor to write to the file.
path (Path | str)
- Return type:
None
Simulation
MAF Output
Writing simulated alignments of k-mer states (e.g. codons) as MAF files.
numpy only. The files can be read with taffy (taffy.lib.AlignmentReader)
or converted to TAF (taffy view -i sim.maf -o sim.taf). Every row is a
gap-free contig named <leaf>.<contig> and the reference row comes first in
every block.
With layout="separator", every k-mer is followed by one separator column
(N by default). Encodings that use all overlapping k-mers of a row, such
as util.tuple_array, then find the separator in every k-mer that straddles two
simulated units; such k-mers are ambiguous (all-ones, i.e. missing data) and
only the simulated k-mers carry likelihood.
- class evoten.maf.MafWriter(file, leaf_names, n_units, *, k=3, layout='separator', separator='N', block_units=250, reference=0, contig='sim', comments=(), min_block_columns=10, mask_char='N')[source]
Bases:
objectStreams alignments of k-mer states into a MAF file.
- Parameters:
file – Path or writable text file handle.
leaf_names (Sequence[str]) – Names of the rows of the states passed to write.
n_units (int) – Total number of units (k-mers per row) that will be written.
k (int) – k-mer length; states are indices into util.tuple_labels(k).
layout (str) – “separator” writes every unit followed by the separator column, “contiguous” writes the units without separators.
separator (str) – Separator character.
block_units (int) – Number of units per MAF block, see block_layout.
reference (int | str) – Index or name of the leaf whose row comes first in every block (taffy and Agrippa treat the first row as the reference).
contig (str | None) – Rows are named f”{leaf}.{contig}”, or just by the leaf name if contig is None.
comments (Iterable[str]) – Strings written as “# “ lines after the header, e.g. “key=value”.
min_block_columns (int) – See block_layout.
mask_char (str) – Character of masked units. The default “N” makes masked units missing data without the gaps that tuple encodings skip.
- close()[source]
Closes the writer (and the file if the writer opened it).
- Returns:
A dict with n_blocks, n_units, n_columns (= src_size), cols_per_unit, layout, block_offsets (unit offsets) and row_names (in file order).
- Return type:
dict
- write(states, mask=None)[source]
Appends units to the alignment and writes all completed blocks.
- Parameters:
states – Integer array (num_rows, n) of k-mer indices < 4**k, rows in the order of leaf_names.
mask – Optional boolean array (num_rows, n); True marks missing units, which are written as mask_char * k.
- Return type:
None
- evoten.maf.block_layout(n_units, block_units, cols_per_unit, min_block_columns=10)[source]
Splits an alignment of n_units units into blocks of block_units units. A last block with fewer than min_block_columns columns is merged into the previous block.
- Parameters:
n_units (int) – Number of units (k-mers) of the alignment.
block_units (int) – Number of units per block.
cols_per_unit (int) – Number of alignment columns per unit.
min_block_columns (int) – Minimum number of columns of a block.
- Returns:
Unit offsets of the blocks, shape (n_blocks + 1,), from 0 to n_units.
- Return type:
ndarray
- evoten.maf.write_maf(file, states, leaf_names, *, mask=None, **kwargs)[source]
Writes an alignment of k-mer states (num_rows, n) as a MAF file.
- Parameters:
file – Path or writable text file handle.
states – Integer array (num_rows, n) of k-mer indices.
leaf_names – Names of the rows of states.
mask – Optional boolean array (num_rows, n) of missing units.
kwargs – Passed to MafWriter.
- Returns:
The dict returned by MafWriter.close.
- Return type:
dict