Skip to content

io

Reading and writing sequences and substitution model data.

sequences

Module for reading and writing sequence files.

Read and write fasta files and multiple sequence alignments in various formats.

labeled_sequences(sequences: dict | list[tuple]) -> list[tuple[str, str]]

Converts dictionaries to lists and keys into strings.

If the keys are TreeNode instances, then their label is taken. Also works if sequences already is a list (of tuples).

Parameters:

Name Type Description Default
sequences dict | list[tuple]

A dictionary mapping keys to sequences, or a list of (key, sequence) tuples.

required

Returns:

Type Description
list[tuple[str, str]]

A list of (label, sequence) tuples, where labels are strings.

Source code in asymmetree/io/sequences.py
def labeled_sequences(sequences: dict | list[tuple]) -> list[tuple[str, str]]:
    """Converts dictionaries to lists and keys into strings.

    If the keys are `TreeNode` instances, then their label is taken. Also works if `sequences`
    already is a list (of tuples).

    Args:
        sequences: A dictionary mapping keys to sequences, or a list of (key, sequence) tuples.

    Returns:
        A list of (label, sequence) tuples, where labels are strings.
    """
    result = []

    if isinstance(sequences, dict):
        sequences = sequences.items()

    for key, sequence in sequences:
        if isinstance(key, TreeNode):
            result.append((str(key.label), sequence))
        else:
            result.append((str(key), sequence))

    return result

write_fasta(file_path: Path | str, sequences: dict | list[tuple]) -> None

Write sequences to a fasta file.

Parameters:

Name Type Description Default
file_path Path | str

The path to the output fasta file.

required
sequences dict | list[tuple]

A dictionary mapping keys to sequences, or a list of (key, sequence) tuples. If the keys are TreeNode instances, then their label is taken as the sequence label.

required
Source code in asymmetree/io/sequences.py
def write_fasta(file_path: Path | str, sequences: dict | list[tuple]) -> None:
    """Write sequences to a fasta file.

    Args:
        file_path: The path to the output fasta file.
        sequences: A dictionary mapping keys to sequences, or a list of (key, sequence) tuples. If
            the keys are `TreeNode` instances, then their label is taken as the sequence label.
    """
    file_path = Path(file_path)
    sequences = labeled_sequences(sequences)

    with file_path.open("w") as f:
        for label, seq in sequences:
            f.write(f">{label}\n")
            pos = 0
            while pos < len(seq):
                f.write(seq[pos : min(pos + 80, len(seq))])
                pos += 80
                f.write("\n")

write_alignment(file_path: Path | str, alignment: dict | list[tuple], alignment_format: str = 'phylip') -> None

Write a multiple sequence alignment to a file.

Parameters:

Name Type Description Default
file_path Path | str

The path to the output alignment file.

required
alignment dict | list[tuple]

A dictionary mapping keys to sequences, or a list of (key, sequence) tuples. If the keys are TreeNode instances, then their label is taken as the sequence label.

required
alignment_format str

The format of the alignment file. Options are "phylip", "clustal", and "pretty".

'phylip'

Raises:

Type Description
ValueError

If the specified alignment format is not available.

Source code in asymmetree/io/sequences.py
def write_alignment(
    file_path: Path | str,
    alignment: dict | list[tuple],
    alignment_format: str = "phylip",
) -> None:
    """Write a multiple sequence alignment to a file.

    Args:
        file_path: The path to the output alignment file.
        alignment: A dictionary mapping keys to sequences, or a list of (key, sequence) tuples. If
            the keys are `TreeNode` instances, then their label is taken as the sequence label.
        alignment_format: The format of the alignment file. Options are "phylip", "clustal", and
            "pretty".

    Raises:
        ValueError: If the specified alignment format is not available.
    """
    alignment = labeled_sequences(alignment)
    file_path = Path(file_path)

    with file_path.open("w") as f:
        if alignment_format == "phylip":
            _write_phylip(f, alignment)
        elif alignment_format == "clustal":
            _write_clustal(f, alignment)
        elif alignment_format == "pretty":
            _write_pretty(f, alignment)
        else:
            raise ValueError(f"alignment format '{alignment_format}' is not available")

substitution_model

Module for reading and writing substitution models.

parse_paml(file_path: Path | str, model_type: str = 'a') -> tuple[list[list[float]], list[float]]

Parse a PAML substitution model file.

Parameters:

Name Type Description Default
file_path Path | str

The path to the PAML file containing the substitution model.

required
model_type str

The type of the substitution model, either "a" for amino acid or "n" for nucleotide.

'a'

Returns:

Type Description
tuple[list[list[float]], list[float]]

A tuple containing the exchangeability matrix and the equilibrium frequencies.

Raises:

Type Description
ValueError

If the model type is not supported.

ValueError

If the number of equilibrium frequencies is not correct.

Source code in asymmetree/io/substitution_model.py
def parse_paml(
    file_path: Path | str,
    model_type: str = "a",
) -> tuple[list[list[float]], list[float]]:
    """Parse a PAML substitution model file.

    Args:
        file_path: The path to the PAML file containing the substitution model.
        model_type: The type of the substitution model, either "a" for amino acid or "n" for
            nucleotide.

    Returns:
        A tuple containing the exchangeability matrix and the equilibrium frequencies.

    Raises:
        ValueError: If the model type is not supported.
        ValueError: If the number of equilibrium frequencies is not correct.
    """
    if model_type == "a":
        # amino acid model
        alphabet_size = 20
    elif model_type == "n":
        # nucleotide model
        alphabet_size = 4
    else:
        raise ValueError(f"model type '{model_type}' not supported")

    file_path = Path(file_path)

    with file_path.open("r") as f:
        exchangeability_matrix = [[0.0 for j in range(alphabet_size)] for i in range(alphabet_size)]

        line = f.readline().strip()
        while line == "":
            line = f.readline().strip()

        for i in range(1, alphabet_size):
            line = [float(item) for item in line.split()]

            for j in range(len(line)):
                exchangeability_matrix[i][j] = line[j]
                exchangeability_matrix[j][i] = line[j]

            line = f.readline().strip()

        line = f.readline().strip()
        while line == "":
            line = f.readline().strip()

        stat_freqs = [float(item) for item in line.split()]

        if len(stat_freqs) != alphabet_size:
            raise ValueError("wrong no. of equilibrium frequencies, check paml file")

        return exchangeability_matrix, stat_freqs