molforge.io¶
io ¶
File I/O for molforge.
This subpackage provides parsers and writers for the file formats you'll
encounter across structural-biology workflows. The top-level entry
points are :func:load, :func:save, and :func:fetch, which dispatch
to the appropriate handler based on the file extension.
Supported formats:
- PDB (
.pdb,.ent) — full read/write, the universal default. - mmCIF / PDBx (
.cif,.mmcif) — full read/write; recommended for structures with >99,999 atoms (PDB's hard limit). - FASTA (
.fasta,.fa,.faa,.fna) — sequence read/write. - SDF (
.sdf,.mol) — small-molecule exchange; full read/write of V2000 (coordinates, elements, title, property block). V3000 is not yet supported. - MOL2 (
.mol2) — Tripos small-molecule exchange; full read/write of the ATOM section (coordinates, elements via Tripos type prefix, atom names, partial charges, substructure info). - PDBQT (
.pdbqt) — AutoDock / Vina format; full read/write of ATOM records with per-atom partial charges and AutoDock atom types, reusing the PDB reader for the leading columns. ROOT / BRANCH / TORSDOF rotatable-bond markers are read-tolerated; round-tripping preserves coordinates, charges, and types. - PQR (
.pqr) — APBS / PDB2PQR with explicit per-atom charges and radii. The leading PDB-compatible columns are parsed as fixed-position; the charge and radius are whitespace-split from the trailing fields (PQR is not strictly fixed-column past the coordinates). Radii are attached toprotein.metadata["radii"].
For MD trajectories:
- :func:
read_trajectory/ :func:iter_trajectory/ :func:write_trajectory— eager and streaming I/O for binary MD trajectories (.xtc,.trr,.dcd,.nc,.h5, plus multi-MODEL PDB). Trajectories are kept off the :func:load/ :func:savedispatcher because they need an explicittopologyargument and return :class:molforge.md.Trajectoryrather than :class:molforge.core.Protein.
Convenience helpers:
- :func:
fetch/ :func:fetch_many— pull one or many structures by PDB ID from RCSB or AlphaFold. - :func:
search_rcsb— full-text search the RCSB PDB for entry IDs, ready to hand to :func:fetch_many. - :func:
fetch_chembl/ :func:fetch_chembl_many— pull one or many small molecules from ChEMBL by ID as :class:~molforge.core.Moleculeobjects. - :func:
load_alphafold— load an AlphaFold prediction, exposing pLDDT as a first-class field rather than buried in B-factor.
Example
import molforge as mf protein = mf.load("1ubq.pdb") mf.save(protein, "1ubq_clean.pdb")
FastaRecord
dataclass
¶
A single record from a FASTA file.
Attributes:
| Name | Type | Description |
|---|---|---|
id |
str
|
The first whitespace-delimited token after |
description |
str
|
The rest of the header line, if any. |
sequence |
str
|
The concatenated, whitespace-stripped sequence. |
metadata |
dict[str, str]
|
Free-form metadata (e.g. for downstream tools). |
CIFParseError ¶
Bases: ValueError
Raised when an mmCIF file cannot be parsed.
CIFWriteError ¶
Bases: ValueError
Raised when an in-memory structure cannot be serialized to mmCIF.
PDBParseError ¶
Bases: ValueError
Raised when a PDB file cannot be parsed.
PDBWriteError ¶
Bases: ValueError
Raised when an in-memory structure cannot be serialized to PDB.
fetch_chembl ¶
Fetch one compound from ChEMBL by ID as a :class:Molecule.
Downloads the entry from the ChEMBL REST API and builds a molecule from its canonical SMILES.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chembl_id
|
str
|
A ChEMBL molecule ID, e.g. |
required |
timeout
|
float
|
Network timeout in seconds. |
30.0
|
sanitize
|
bool
|
Run RDKit sanitization when parsing the SMILES. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
Molecule
|
class: |
Molecule
|
ID when there's none), with |
|
Molecule
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
OSError
|
If the download fails — network error, timeout, or a non-2xx response (a 404 for an unknown ID). |
RDKitNotInstalledError
|
If RDKit isn't installed. |
Example
from molforge.io import fetch_chembl aspirin = fetch_chembl("CHEMBL25")
fetch_chembl_many ¶
fetch_chembl_many(
chembl_ids: Iterable[str],
*,
timeout: float = 30.0,
sanitize: bool = True,
on_error: str = "raise",
) -> list[Molecule]
Fetch several ChEMBL compounds by ID, one :func:fetch_chembl per ID.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
chembl_ids
|
Iterable[str]
|
The ChEMBL IDs to fetch, in the order you want them back. |
required |
timeout
|
float
|
Per-download network timeout in seconds. |
30.0
|
sanitize
|
bool
|
Run RDKit sanitization when parsing each SMILES. |
True
|
on_error
|
str
|
|
'raise'
|
Returns:
| Type | Description |
|---|---|
list[Molecule]
|
The fetched molecules, in input order (minus any dropped under |
list[Molecule]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
OSError
|
On a download failure when |
RDKitNotInstalledError
|
If RDKit isn't installed. |
fetch ¶
fetch(
pdb_id: str,
*,
source: str = "rcsb",
format: str = "pdb",
timeout: float = 30.0,
) -> Protein
Fetch a structure by ID from a remote source.
Downloads the structure over HTTPS and parses it into a
:class:~molforge.core.Protein. Uses only the standard library
(:mod:urllib), so it adds no dependency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pdb_id
|
str
|
4-character PDB ID (for |
required |
source
|
str
|
|
'rcsb'
|
format
|
str
|
|
'pdb'
|
timeout
|
float
|
Network timeout in seconds for the download. |
30.0
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
Protein
|
class: |
Protein
|
file. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
OSError
|
If the download fails — network error, timeout, or a
non-existent ID (which the server returns as HTTP 404).
The underlying :class: |
Example
from molforge.io import fetch protein = fetch("1ABC") # RCSB, PDB format af = fetch("P00520", source="alphafold") # AlphaFold DB
fetch_many ¶
fetch_many(
pdb_ids: Iterable[str],
*,
source: str = "rcsb",
format: str = "pdb",
timeout: float = 30.0,
on_error: str = "raise",
) -> list[Protein]
Fetch several structures by ID, one :func:fetch per ID.
A thin convenience over :func:fetch for pulling a whole set — for
example the hits from :func:search_rcsb. Downloads are sequential (the
servers rate-limit, and this keeps the dependency to the standard library).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pdb_ids
|
Iterable[str]
|
The IDs to fetch, in the order you want them back. |
required |
source
|
str
|
|
'rcsb'
|
format
|
str
|
|
'pdb'
|
timeout
|
float
|
Per-download network timeout in seconds. |
30.0
|
on_error
|
str
|
|
'raise'
|
Returns:
| Type | Description |
|---|---|
list[Protein]
|
The fetched proteins, in input order (minus any dropped under |
list[Protein]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
OSError
|
On a download failure when |
load ¶
Load a structure or sequence file.
Format is inferred from the extension unless format is given.
Additional kwargs are forwarded to the underlying reader.
Returns:
| Name | Type | Description |
|---|---|---|
A |
object
|
class: |
object
|
class: |
save ¶
save(
obj: object,
path: str | PathLike[str],
*,
format: str | None = None,
**kwargs: object,
) -> None
Save a structure or list of FASTA records to disk.
Format is inferred from the extension unless format is given.
read_fasta ¶
Read a FASTA file from disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
Path to a |
required |
Returns:
| Type | Description |
|---|---|
list[FastaRecord]
|
A list of :class: |
read_fasta_string ¶
Parse FASTA-formatted text, yielding :class:FastaRecord objects.
Memory-efficient: yields records one at a time rather than building a list up front.
write_fasta ¶
write_fasta(
records: Iterable[FastaRecord | tuple[str, str]],
path: str | PathLike[str],
*,
line_width: int = 80,
) -> None
Write FASTA records to disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
records
|
Iterable[FastaRecord | tuple[str, str]]
|
Iterable of :class: |
required |
path
|
str | PathLike[str]
|
Destination path; |
required |
line_width
|
int
|
Maximum sequence characters per line. Set to |
80
|
write_fasta_string ¶
write_fasta_string(
records: Iterable[FastaRecord | tuple[str, str]],
*,
line_width: int = 80,
) -> str
Serialize records as FASTA-formatted text.
read_cif ¶
read_cif(
path: str | PathLike[str],
*,
include_hydrogens: bool = True,
altloc: str = "highest_occupancy",
) -> Protein
Read an mmCIF / PDBx file from disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
Path to a |
required |
include_hydrogens
|
bool
|
If False, drop hydrogen atoms during parsing. |
True
|
altloc
|
str
|
Altloc-resolution strategy (same as :func: |
'highest_occupancy'
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
Protein
|
class: |
Protein
|
populated with |
|
Protein
|
and |
Raises:
| Type | Description |
|---|---|
CIFParseError
|
If the file is malformed or has no |
FileNotFoundError
|
If the path doesn't exist. |
read_cif_string ¶
read_cif_string(
text: str,
*,
include_hydrogens: bool = True,
altloc: str = "highest_occupancy",
) -> Protein
Parse mmCIF-formatted text into a :class:Protein.
See :func:read_cif for argument semantics.
write_cif ¶
Write a :class:Protein to an mmCIF file.
write_cif_string ¶
Serialize a :class:Protein as mmCIF text.
Produces a compact CIF with a data_<id> header, the structure's
metadata (where present), and a complete _atom_site loop. Round-trips
cleanly through :func:read_cif_string.
iter_molecules ¶
iter_molecules(
path: str | PathLike[str],
*,
format: str | None = None,
sanitize: bool = True,
) -> Iterator[Molecule]
Stream a molecule file into :class:Molecule objects, one at a time.
The lazy counterpart to :func:read_molecules: SDF is streamed with
RDKit's ForwardSDMolSupplier and SMILES line by line, so a file
larger than memory can be processed without materializing it. The format
is resolved eagerly (so a bad extension or format raises right away),
while per-record parsing stays lazy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The file to read. |
required |
format
|
str | None
|
|
None
|
sanitize
|
bool
|
Run RDKit sanitization on each molecule. |
True
|
Returns:
| Type | Description |
|---|---|
Iterator[Molecule]
|
A lazy iterator of molecules, in file order; each records the source |
Iterator[Molecule]
|
file in its metadata and takes its |
Raises:
| Type | Description |
|---|---|
RDKitNotInstalledError
|
If RDKit isn't installed (raised when the iterator is first consumed). |
ValueError
|
On an unknown format (raised eagerly). |
iter_smiles ¶
Stream a SMILES block into molecules, one line at a time.
The lazy counterpart to :func:read_smiles — same SMILES [name]
per-line format (blank lines and # comments skipped), but molecules
are yielded as each line is parsed rather than collected into a list.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
The SMILES text. |
required |
sanitize
|
bool
|
Run RDKit sanitization on each molecule. |
True
|
source
|
str
|
Recorded in each molecule's |
'<string>'
|
Yields:
| Name | Type | Description |
|---|---|---|
One |
Molecule
|
class: |
Raises:
| Type | Description |
|---|---|
RDKitNotInstalledError
|
If RDKit isn't installed. |
ValueError
|
If a SMILES string can't be parsed. |
read_molecules ¶
read_molecules(
path: str | PathLike[str],
*,
format: str | None = None,
sanitize: bool = True,
) -> list[Molecule]
Read a molecule file into chemistry-aware :class:Molecule objects.
Supports SDF (.sdf / .mol) and SMILES (.smi / .smiles).
SDF records RDKit can't parse are skipped so one bad entry doesn't sink
a bulk read. Each molecule records the source file in its metadata and
takes its name from the record (the SDF title or the SMILES name
column).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
The file to read. |
required |
format
|
str | None
|
|
None
|
sanitize
|
bool
|
Run RDKit sanitization on each molecule. |
True
|
Returns:
| Type | Description |
|---|---|
list[Molecule]
|
The molecules, in file order. |
Raises:
| Type | Description |
|---|---|
RDKitNotInstalledError
|
If RDKit isn't installed. |
ValueError
|
On an unknown format. |
read_smiles ¶
Parse a SMILES block into molecules.
One molecule per line, SMILES [name] (whitespace-separated); blank
lines and # comments are skipped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
The SMILES text. |
required |
sanitize
|
bool
|
Run RDKit sanitization on each molecule. |
True
|
source
|
str
|
Recorded in each molecule's |
'<string>'
|
Returns:
| Type | Description |
|---|---|
list[Molecule]
|
The parsed molecules, in file order. |
Raises:
| Type | Description |
|---|---|
RDKitNotInstalledError
|
If RDKit isn't installed. |
ValueError
|
If a SMILES string can't be parsed. |
read_pdb ¶
read_pdb(
path: str | PathLike[str],
*,
model: int | None = None,
include_hydrogens: bool = True,
altloc: str = "highest_occupancy",
) -> Protein
Read a PDB file from disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
Path to a |
required |
model
|
int | None
|
Which model to load from a multi-model file. |
None
|
include_hydrogens
|
bool
|
If |
True
|
altloc
|
str
|
Strategy for resolving alternate location indicators.
|
'highest_occupancy'
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
Protein
|
class: |
Protein
|
|
|
Protein
|
and EXPDTA records found. |
Raises:
| Type | Description |
|---|---|
PDBParseError
|
If the file is malformed. |
FileNotFoundError
|
If the path doesn't exist. |
read_pdb_string ¶
read_pdb_string(
text: str,
*,
model: int | None = None,
include_hydrogens: bool = True,
altloc: str = "highest_occupancy",
) -> Protein
Parse a PDB-formatted string into a :class:Protein.
See :func:read_pdb for argument semantics.
write_pdb ¶
Write a :class:Protein to a PDB file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
protein
|
Protein
|
the structure to serialize. |
required |
path
|
str | PathLike[str]
|
destination path. |
required |
write_end
|
bool
|
emit a final |
True
|
Raises:
| Type | Description |
|---|---|
PDBWriteError
|
If the structure exceeds PDB's hard limits (>99,999 atoms or >9,999 residues per chain). |
write_pdb_string ¶
Serialize a :class:Protein into a PDB-formatted string.
is_alphafold_pdb ¶
Detect whether a PDB file/string is an AlphaFold prediction.
Heuristic: looks for ALPHAFOLD, PREDICTED MODEL, or ESMFOLD
in the first 100 lines of HEADER / TITLE / REMARK records.
load_alphafold ¶
Load an AlphaFold prediction, exposing pLDDT as metadata.
The protein is read via :func:molforge.io.read_pdb, then its
metadata is populated with confidence information under two
sets of keys:
- Uniform folding-engine keys (preferred) — the same keys
every molforge folding-engine wrapper sets, so downstream code
can read confidence without caring which engine ran:
confidence_per_atom,confidence_per_residue,mean_confidence, andengine(="AlphaFold"). - Legacy AlphaFold-specific keys (retained for backward
compatibility):
plddt,plddt_per_residue,mean_plddt,source(="alphafold").
The two sets carry the same values; new code should prefer the
uniform keys. See :mod:molforge.core.metadata_keys for the
documented vocabulary.
The B-factor column is left intact for compatibility with downstream tools that still expect to find pLDDT there.
search_rcsb ¶
Full-text search the RCSB PDB, returning matching entry IDs.
Runs a full-text query against the RCSB Search API and returns the PDB
IDs of the best matches, most relevant first — feed them to
:func:molforge.io.fetch_many to download the structures.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
Free-text query, e.g. |
required |
limit
|
int
|
Maximum number of IDs to return (the top |
25
|
timeout
|
float
|
Network timeout in seconds. |
30.0
|
Returns:
| Type | Description |
|---|---|
list[str]
|
Up to |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
OSError
|
If the search request fails — network error, timeout, or a non-2xx response from RCSB. |
Example
from molforge.io import search_rcsb, fetch_many ids = search_rcsb("hemoglobin", limit=5) structures = fetch_many(ids)
iter_trajectory ¶
iter_trajectory(
path: str | PathLike[str],
*,
topology: Protein | str | PathLike[str] | None = None,
chunk_size: int = 100,
stride: int = 1,
atom_indices: list[int] | ndarray | None = None,
fmt: str | None = None,
) -> Iterator[Trajectory]
Stream a trajectory in chunks of frames.
Use this for trajectories larger than RAM. Each yielded object is
a :class:molforge.md.Trajectory holding chunk_size frames
(the last chunk may be shorter); memory usage is bounded by
chunk_size × n_atoms × 12 bytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
Trajectory file. |
required |
topology
|
Protein | str | PathLike[str] | None
|
As for :func: |
None
|
chunk_size
|
int
|
Number of frames per yielded Trajectory. Default 100; balance memory vs iteration overhead. |
100
|
stride
|
int
|
Read every |
1
|
atom_indices
|
list[int] | ndarray | None
|
Read only these atom indices. |
None
|
Yields:
| Name | Type | Description |
|---|---|---|
A |
Trajectory
|
class: |
Raises:
| Type | Description |
|---|---|
MDEngineNotInstalledError
|
If mdtraj is not installed. |
ValueError
|
If |
Example
for chunk in iter_trajectory("big.xtc", topology=top, chunk_size=500): ... # process chunk.coordinates here; memory bounded ... pass
read_trajectory ¶
read_trajectory(
path: str | PathLike[str],
*,
topology: Protein | str | PathLike[str] | None = None,
stride: int = 1,
atom_indices: list[int] | ndarray | None = None,
fmt: str | None = None,
) -> Trajectory
Read a trajectory file into a :class:molforge.md.Trajectory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | PathLike[str]
|
Path to the trajectory. Format inferred from the
extension unless |
required |
topology
|
Protein | str | PathLike[str] | None
|
The topology to attach. Required for formats that
don't embed topology ( |
None
|
stride
|
int
|
Read every |
1
|
atom_indices
|
list[int] | ndarray | None
|
Read only these atom indices (0-based). Useful
when an analysis only touches a subset (e.g. backbone
atoms). When given, the resulting :class: |
None
|
fmt
|
str | None
|
Override the format inference. Passed to mdtraj as the file extension (without the leading dot). |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
Trajectory
|
class: |
Trajectory
|
in picoseconds when available, and the topology as a |
|
Trajectory
|
class: |
|
Trajectory
|
memory — use :func: |
|
Trajectory
|
fit. |
Raises:
| Type | Description |
|---|---|
MDEngineNotInstalledError
|
If mdtraj is not installed. |
ValueError
|
If |
Example
from molforge.io import read_pdb, read_trajectory topology = read_pdb("system.pdb") traj = read_trajectory("md.xtc", topology=topology) traj.n_frames 1000 traj.coordinates.shape # (n_frames, n_atoms, 3) in Å (1000, 24512, 3)
write_trajectory ¶
write_trajectory(
trajectory: Trajectory,
path: str | PathLike[str],
*,
fmt: str | None = None,
) -> None
Write a :class:Trajectory to disk.
The format is inferred from the path's extension. Coordinates are converted from Å (molforge convention) to nm (mdtraj's convention) on the way out.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trajectory
|
Trajectory
|
The :class: |
required |
path
|
str | PathLike[str]
|
Output path. Format inferred from the extension. |
required |
Raises:
| Type | Description |
|---|---|
MDEngineNotInstalledError
|
If mdtraj is not installed. |
Example
from molforge.io import write_trajectory write_trajectory(traj, "out.xtc")