Skip to main content

tofasta

Convert pandas DataFrames and CSV files to FASTA, with validation that refuses to write malformed output.

FASTA has no formal specification, so every consumer is permissive. Feed BLAST or MMseqs2 a file with duplicate headers, an empty sequence, or an identifier containing a space, and you will not get an error. You will get results that are quietly wrong. tofasta checks for those cases up front and raises instead of writing.

Install

pip install tofasta

Use

import pandas as pd
from tofasta import to_fasta

df = pd.DataFrame({
    "accession": ["96602692", "77cd04d8"],
    "sequence": ["MKVLAAGIVL", "GSGEGPREPG"],
})

to_fasta(df, "out.fasta", id="accession", seq="sequence")
>96602692
MKVLAAGIVL
>77cd04d8
GSGEGPREPG

Straight from a CSV:

from tofasta import csv_to_fasta

csv_to_fasta("in.csv", "out.fasta", id="accession", seq="sequence")

Or from the shell:

tofasta in.csv out.fasta --id accession --seq sequence

Both return the number of records written, so you can assert on it.

What it checks

Problem Why it matters
Duplicate identifiers Accepted silently by BLAST and MMseqs2, producing wrong results rather than errors
Missing or empty identifier Becomes a headerless or garbage record
Missing or empty sequence Produces a header with no residues
Whitespace in an identifier Parsers stop at the first space, so the identifier is silently truncated
> in an identifier Starts a new record mid-header
Line breaks in any field Corrupts the record structure
Whitespace inside a sequence Usually a stray column or a copy-paste artifact
Numeric sequence column A float column would otherwise be written out as 1.0

Residue validation is opt in, via alphabet="protein", "dna", "rna", or any iterable of permitted characters. It is off by default because real curated data legitimately contains X at unresolved positions, and a validator that fights real data gets switched off entirely.

Output is always LF terminated, on every platform.

Options

to_fasta(
    df,
    path_or_buf,        # path, or anything with a .write method
    *,
    id,                 # identifier column
    seq,                # sequence column
    description=None,   # optional column appended to the header after a space
    wrap=None,          # wrap sequences at N characters
    on_duplicate="raise",   # or "warn", or "first"
    alphabet=None,      # "protein", "dna", "rna", or an iterable of characters
)

On wrapping

Sequences are written on a single line by default. Wrapping at 60 or 80 characters is a widespread convention rather than a rule, and NCBI states only that lines should be "shorter than 80 characters". No parser written in the last thirty years cares, because they all concatenate lines until the next >.

Single-line output also keeps MMseqs2's --createdb-mode 1 available, which soft-links the input instead of copying it and requires single-line records.

Pass wrap=60 if you want the conventional look.

Documentation

Full API reference documentation is available at readthedocs.

Scope

This library writes FASTA. It does not read it. Reading looks symmetric but is not: you would own indexing, compression, malformed-record recovery, and memory behaviour on multi-gigabyte files. Use pyfastx or Biopython for that.

If you need sequence objects, alignment, translation, or other file formats, you want Biopython. tofasta exists for the narrow case where you already have a DataFrame and want a correct FASTA file out of it without building intermediate record objects.

Prior art

Biopython writes FASTA reliably via SeqIO.write. It requires you to build SeqRecord objects, silently appends <unknown description> if you forget description="", hard-wraps at 60 with no way to disable it, and has no DataFrame awareness. tofasta is a smaller, narrower tool for that specific gap.

Several of the checks here are regression tests against real defects in CDC's CSV2FASTA browser tool, which emits CRLF unconditionally and writes a phantom >undefined record with an empty sequence whenever the identifier is not the first column of the input.

Development

uv sync
uv run pytest

To build the documentation, use the same flags Read the Docs does. The -W and -j auto both matter: warnings are errors there, and parallel builds surface extension incompatibilities that a serial build hides.

uv sync --extra docs
uv run python -m sphinx -T -W --keep-going -j auto -b html docs docs/_build/html

Licence

MIT

Metadata

Release files for tofasta 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tofasta 0.1.0
File Size Uploaded Provenance
tofasta-0.1.0.tar.gz 77.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tofasta 0.1.0
File Interpreter ABI Platform
tofasta-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 86.4 kB

Release files / tofasta-0.1.0.tar.gz

Download URL tofasta-0.1.0.tar.gz
Size 77.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9eca63784b9aa16a465d0137f10d199aa23da1921a68a99a69e99dc571e25439
BLAKE2b-256 checksum
How to use checksums
5681561d3d80a65c4ec076ec44f13700fe91d54ab7fccd3df6eaa850f8c06750
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / tofasta-0.1.0-py3-none-any.whl

Download URL tofasta-0.1.0-py3-none-any.whl
Size 9.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9ce7197baaa0e0c6d7e195b36e90f5fc67840b777596777a2a964e00fce39af8
BLAKE2b-256 checksum
How to use checksums
d69ccb12f95bef20423fa19008d7666185018541fe23a5ddefcee28900faf21a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for tofasta 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page