Skip to content

Python API

The full surface of the pymafft package, generated from the docstrings in crates/pymafft/python/pymafft/__init__.py and the PyO3 classes in crates/pymafft/src/lib.rs. Four entry-point functions, two result types, one exception, and a stable iteration protocol.

One flag layer, two front ends

Every pymafft function builds a mafft-rs command line from its keyword arguments and runs it in-process through the CLI's own flag layer (mafft_rs::run_from_seqs). Nothing about a flag's meaning is re-derived in Python — --auto's size heuristic, --adjustdirection's strand detection, --nuc's type forcing and case fold, --thread's pool, --reorder, the scoring matrices and gap penalties are all decided by the same code the binary runs — so for the same input and flags the Python result is byte-identical to the CLI's stdout:

import pymafft

# == `mafft-rs --auto --adjustdirection --thread 1 --nuc --quiet genes.fa`
result = pymafft.align(
    [("gene_1", "ATGGCTAGCTTGGACC"), ("gene_2", "GGTCCAAGCTAGCCAT")],
    strategy="auto", adjust_direction=True, threads=1, seq_type="nuc",
)

That is the flag set panaroo passes for its gene-cluster alignments; with pymafft it runs over an in-memory list, with no temporary FASTA files and no FASTA re-parsing.

Keyword CLI flag Values
strategy — / --maxiterate N / --globalpair / --localpair / --genafpair / --auto "fftns2" (default), "fftnsi", "ginsi", "linsi", "einsi", "auto"
maxiterate --maxiterate N 0 = strategy default (100 for fftnsi, 1000 for ginsi / linsi / einsi); ignored by fftns2
seq_type --nuc / --amino None (detect from the residues, as the CLI does), "nuc", "amino"
adjust_direction --adjustdirection / --adjustdirectionaccurately False, True, "accurately"
threads --thread N 0 = all cores
reorder --reorder bool
retree --retree N None = CLI default (2)
scoring --bl N / --jtt N / --tm N "bl30""bl80", "jtt200", "tm100", …
gap_open / gap_extend --op X / --ep X floats (CLI defaults 1.53 / 0.123)
quiet --quiet default True; ignored when progress is given
progress (stderr) callable receiving each progress line

Flags without a keyword go through pymafft.run, which takes the flag list verbatim.

Functions

pymafft.align

align

align(
    sequences: SequenceInput,
    strategy: str = "fftns2",
    maxiterate: int = 0,
    *,
    seq_type: Optional[str] = None,
    adjust_direction: Union[bool, str] = False,
    threads: int = 0,
    reorder: bool = False,
    retree: Optional[int] = None,
    scoring: Optional[str] = None,
    gap_open: Optional[float] = None,
    gap_extend: Optional[float] = None,
    quiet: bool = True,
    progress: Optional[ProgressCallback] = None
) -> AlignmentResult

Align sequences.

Every option maps to one mafft-rs command-line flag and is applied by the CLI's own flag layer, so the result is byte-identical to running mafft-rs with those flags on a FASTA file of the same sequences.

PARAMETER DESCRIPTION
sequences

The sequences to align. Accepted shapes: a list of strings (auto-named seq_1, seq_2, ...); a list of (name, sequence) tuples; an iterable of objects with .id and .seq attributes (e.g. Biopython SeqRecord).

TYPE: SequenceInput

strategy

"fftns2" (default; FFT-NS-2), "fftnsi" (--maxiterate N), "ginsi" (--globalpair), "linsi" (--localpair), "einsi" (--genafpair) or "auto" (--auto: strategy chosen from the input size).

TYPE: str DEFAULT: 'fftns2'

maxiterate

Refinement cycles (--maxiterate). 0 means the strategy's default: 100 for fftnsi, 1000 for ginsi / linsi / einsi; fftns2 never refines and auto decides for itself.

TYPE: int DEFAULT: 0

seq_type

None detects the type from the residues as the CLI does; "nuc" / "amino" force it (--nuc / --amino).

TYPE: Optional[str] DEFAULT: None

adjust_direction

True for --adjustdirection (k-mer strand detection, DNA only), "accurately" for --adjustdirectionaccurately (DP-based).

TYPE: Union[bool, str] DEFAULT: False

threads

--thread N; 0 (default) uses all cores.

TYPE: int DEFAULT: 0

reorder

--reorder: output rows in guide-tree order.

TYPE: bool DEFAULT: False

retree

--retree N guide-tree rebuilds (CLI default 2).

TYPE: Optional[int] DEFAULT: None

scoring

Substitution matrix: "bl30" ... "bl80" (--bl), "jtt200" (--jtt), "tm100" (--tm).

TYPE: Optional[str] DEFAULT: None

gap_open

--op gap opening penalty (CLI default 1.53).

TYPE: Optional[float] DEFAULT: None

gap_extend

--ep offset / gap extension penalty (CLI default 0.123).

TYPE: Optional[float] DEFAULT: None

quiet

Pass --quiet, suppressing progress messages. Ignored when progress is given.

TYPE: bool DEFAULT: True

progress

Callable receiving each progress line (the text the CLI prints on stderr without --quiet, one call per line, no trailing newline). With progress=None and quiet=False the lines go to the process's stderr, as on the command line.

TYPE: Optional[ProgressCallback] DEFAULT: None

RETURNS DESCRIPTION
AlignmentResult

AlignmentResult with the aligned sequences. Nucleotide output is

AlignmentResult

lowercase and protein output uppercase, as with C MAFFT.

RAISES DESCRIPTION
MafftError

When the alignment fails, e.g. on an illegal residue; .code and .message are the CLI's exit code and stderr text. A ValueError subclass.

ValueError

If sequences is empty or has an unsupported shape, or an option value is invalid.

pymafft.align_file

align_file

align_file(
    path: str,
    strategy: str = "fftns2",
    maxiterate: int = 0,
    *,
    seq_type: Optional[str] = None,
    adjust_direction: Union[bool, str] = False,
    threads: int = 0,
    reorder: bool = False,
    retree: Optional[int] = None,
    scoring: Optional[str] = None,
    gap_open: Optional[float] = None,
    gap_extend: Optional[float] = None,
    quiet: bool = True,
    progress: Optional[ProgressCallback] = None
) -> AlignmentResult

Align sequences from a FASTA file.

Same options as :func:align; the file is read with the CLI's FASTA reader.

PARAMETER DESCRIPTION
path

Path to the FASTA file.

TYPE: str

RAISES DESCRIPTION
ValueError

If the file cannot be read or parsed.

MafftError

If the alignment fails (see :func:align).

pymafft.align_fasta_string

align_fasta_string

align_fasta_string(
    fasta_string: str,
    strategy: str = "fftns2",
    maxiterate: int = 0,
    *,
    seq_type: Optional[str] = None,
    adjust_direction: Union[bool, str] = False,
    threads: int = 0,
    reorder: bool = False,
    retree: Optional[int] = None,
    scoring: Optional[str] = None,
    gap_open: Optional[float] = None,
    gap_extend: Optional[float] = None,
    quiet: bool = True,
    progress: Optional[ProgressCallback] = None
) -> AlignmentResult

Align sequences from a FASTA-formatted string.

Same options as :func:align; the text is parsed with the CLI's FASTA reader.

PARAMETER DESCRIPTION
fasta_string

FASTA-formatted text.

TYPE: str

RAISES DESCRIPTION
ValueError

If the string cannot be parsed as FASTA.

MafftError

If the alignment fails (see :func:align).

pymafft.run

run

run(
    args: Sequence[str],
    sequences: SequenceInput,
    *,
    progress: Optional[ProgressCallback] = None
) -> AlignmentResult

Align with an explicit mafft-rs command line.

The escape hatch for flags that have no keyword in :func:align: args is passed verbatim (without the program name and without an input path; the sequences take its place) to the same entry point :func:align uses, so run(["--auto", "--nuc", "--quiet"], seqs) equals align(seqs, strategy="auto", seq_type="nuc").

PARAMETER DESCRIPTION
args

The flags, e.g. ["--localpair", "--maxiterate", "1000", "--quiet"]. Progress goes to stderr unless --quiet is present or progress is given.

TYPE: Sequence[str]

sequences

As for :func:align.

TYPE: SequenceInput

progress

As for :func:align. The flags are not modified, so add --quiet yourself to silence stderr when progress is None.

TYPE: Optional[ProgressCallback] DEFAULT: None

RAISES DESCRIPTION
MafftError

For any failure the CLI would exit on, including unknown flags (.message is clap's usage text) and an INPUT path in args.

Result types

AlignmentResult

The object returned by every alignment function. It's iterable, length- addressable, indexable, and convertible to FASTA / tuples / Biopython.

Result of a multiple sequence alignment.

sequences property

sequences: list[AlignedSequence]

width property

width: int

score property

score: float

nseq property

nseq: int

to_fasta

to_fasta() -> str

Return the alignment as a FASTA-formatted string.

to_tuples

to_tuples() -> list[tuple[str, str]]

Return the alignment as a list of (name, sequence) tuples.

to_biopython

to_biopython() -> Any

Return the alignment as a Bio.Align.MultipleSeqAlignment.

Each row becomes a Bio.SeqRecord.SeqRecord with id set to the sequence name and an empty description. Biopython is imported lazily here and only here; it is not a dependency of pymafft.

RAISES DESCRIPTION
ImportError

If Biopython is not installed.

AlignedSequence

A single aligned row.

A single aligned sequence with name and gapped data.

name property

name: str

sequence property

sequence: str

ungapped

ungapped() -> str

Return the sequence without gap characters.

Errors

MafftError

Bases: ValueError

Raised when the alignment fails.

Carries the exact stderr text and exit code the mafft-rs command line would have produced for the same input and flags. A ValueError subclass, so except ValueError keeps working.

code instance-attribute

code: int

Exit code the CLI would terminate with (1 for an illegal residue, 2 for a clap usage error, 0 for an informational early exit).

message instance-attribute

message: str

The CLI's stderr text, without the trailing newline; also str(err).

Everything the command line would exit on is raised as pymafft.MafftError, with the CLI's exit code in .code and its stderr text in .message (also str(err)). It subclasses ValueError, so existing except ValueError handlers keep working.

try:
    pymafft.align([("p1", "MKTAYUAKQR"), ("p2", "MKTAYIAKQR")])
except pymafft.MafftError as e:
    print(e.code, e.message)   # 1 Illegal character U

With quiet=False the message carries the same multi-line banner the CLI prints (=== Alphabet 'U' is unknown. …). Residues outside the alphabet can be kept with --anysymbol through run.

Errors that are not the CLI's — an empty sequence list, an unsupported input shape, an unreadable file, an invalid keyword value — stay plain ValueError / TypeError.

Progress

The CLI reports what it is doing on stderr (mafft-rs v0.2.0, 36 sequences (aa), strategy: FFT-NS-2, Alignment: 717 columns). pymafft is quiet by default; pass a callable to receive exactly those lines, one call per line without the trailing newline:

lines = []
pymafft.align(seqs, strategy="auto", progress=lines.append)
# or straight into a logger
pymafft.align(seqs, progress=logging.getLogger("mafft").info)

quiet=False without a callable writes them to the process's stderr, as the command line does (file descriptor 2, not sys.stderr). An exception raised inside the callable is re-raised after the run returns.

The alignment runs with the GIL released, so several Python threads can align concurrently; threads controls the Rust-side pool of each call.

Input shapes

pymafft.align and pymafft.run accept three shapes interchangeably:

# 1. Bare strings — auto-named seq_1, seq_2, ...
pymafft.align(["ACDEFGHIK", "ACDEFHIK"])

# 2. (name, seq) tuples
pymafft.align([("alpha", "ACDEFGHIK"), ("beta", "ACDEFHIK")])

# 3. Any object with `.id` and `.seq` attributes — duck-types
#    Biopython's SeqRecord, scikit-bio's Sequence, etc.
from Bio.SeqRecord import SeqRecord
from Bio.Seq import Seq
records = [
    SeqRecord(Seq("ACDEFGHIK"), id="alpha"),
    SeqRecord(Seq("ACDEFHIK"),  id="beta"),
]
pymafft.align(records)

Residues are handled exactly as the CLI's FASTA reader handles them: the sequence type is detected from the ATGC frequency unless seq_type forces it, nucleotide residues are lowercased and protein residues uppercased (C MAFFT's convention, so the output case matches the CLI's), * becomes -, and a residue outside the alphabet raises MafftError.

For full Biopython interop including MultipleSeqAlignment round-trips, see Biopython interop.

Output shapes

result = pymafft.align(seqs)

# Iterate
for aligned in result:
    print(aligned.name, aligned.sequence)

# Index
result[0].sequence       # first aligned row
len(result)              # number of sequences

# Aggregate views
result.to_fasta()        # FASTA-formatted string (one line per row)
result.to_tuples()       # [(name, gapped_seq), ...]
result.to_biopython()    # Bio.Align.MultipleSeqAlignment (lazy import)
result.width             # alignment width (uniform across rows)
result.score             # final SP score

Strategy parameter

pymafft.align(seqs, strategy="fftns2", maxiterate=0)   # default, == `mafft-rs`
pymafft.align(seqs, strategy="fftnsi", maxiterate=1000) # == --maxiterate 1000
pymafft.align(seqs, strategy="linsi",  maxiterate=1000) # == --localpair --maxiterate 1000
pymafft.align(seqs, strategy="ginsi",  maxiterate=1000) # == --globalpair --maxiterate 1000
pymafft.align(seqs, strategy="einsi",  maxiterate=1000) # == --genafpair --maxiterate 1000
pymafft.align(seqs, strategy="auto")                    # == --auto

See Choosing a strategy for the trade-offs.

CLI from Python

pip install pymafft also drops a mafft-rs console script on $PATH (via the wheel-bundled native binary). Two equivalent invocations after install:

mafft-rs --help
python -m pymafft --help

See the CLI reference for the flag list. Any flag listed there can also be passed in-process through pymafft.run.