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
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tofasta-0.1.0.tar.gz.
File metadata
- Download URL: tofasta-0.1.0.tar.gz
- Upload date:
- Size: 77.0 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9eca63784b9aa16a465d0137f10d199aa23da1921a68a99a69e99dc571e25439
|
|
| MD5 |
3541c6656ede0438eb90bcde9bba1cca
|
|
| BLAKE2b-256 |
5681561d3d80a65c4ec076ec44f13700fe91d54ab7fccd3df6eaa850f8c06750
|
File details
Details for the file tofasta-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tofasta-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ce7197baaa0e0c6d7e195b36e90f5fc67840b777596777a2a964e00fce39af8
|
|
| MD5 |
d8c71d292d176ed8e5a281c46bb954ba
|
|
| BLAKE2b-256 |
d69ccb12f95bef20423fa19008d7666185018541fe23a5ddefcee28900faf21a
|