SABLE is a versioned antibody-structure benchmark for machine-learning evaluation. The data release is hosted on Zenodo as flat files, while this repository provides the Python package that downloads, verifies, extracts, filters, and loads the dataset for analysis and PyTorch training.
The large PDB archives are not stored in GitHub. Install the package, then use download=True or the sable-download command to fetch the fixed SABLE release from Zenodo into a local cache.
Please visit the SABLE Zenodo and the SABLE web-server for the full data documentation and guides.
PyTorch utilities and Parquet metadata loading are included in the core installation.
git clone https://github.com/dina-lab3D/SABLE.git
cd SABLE
pip install -e ".[dev]"
pytestfrom sable import SableDataset
train = SableDataset(
root="~/data/sable",
split="train",
synthetic=False,
non_redundant=True,
version="0.1.0",
download=True,
record_id="20809003",
)
ab = train[0]
print(ab.entry_id)
print(ab.pdb_id)
print(ab.heavy_sequence)
print(ab.region_sequence("H", "CDR3"))
print(ab.structure_path)SableDataset returns Antibody objects by default. If you pass a transform, each item is the transformed sample instead.
SABLE has two metadata splits: train and test. Training rows can be experimental or synthetic, and experimental rows can be redundant or non-redundant. SableDataset exposes these as composable filters:
from sable import SableDataset
all_train = SableDataset(root="~/data/sable", split="train")
experimental_train = SableDataset(
root="~/data/sable",
split="train",
synthetic=False,
)
synthetic_train = SableDataset(
root="~/data/sable",
split="train",
experimental=False,
)
non_redundant_experimental = SableDataset(
root="~/data/sable",
split="train",
synthetic=False,
non_redundant=True,
)
protein_or_peptide_antigens = SableDataset(
root="~/data/sable",
split="train",
has_antigen_only=True,
has_aa_antigen_only=True,
)The main filters are:
| Argument | Meaning |
|---|---|
split |
Keep only "train" or "test" rows. Leave as None to keep both. |
experimental |
Include experimental structures. Set False to keep only synthetic entries. |
synthetic |
Include synthetic entries. Set False to keep only experimental entries. |
non_redundant |
Keep only rows marked as non-redundant. |
has_antigen_only |
Keep only rows with an antigen annotation. |
has_aa_antigen_only |
Keep only rows whose antigen type includes protein or peptide. |
Useful dataset helpers:
len(train)
train.entry_ids
train.get_by_entry_id("10en_0")
train.to_dataframe()
for antibody in train.iter_antibodies():
...An Antibody wraps one metadata row and lazily resolves its processed structure file.
Common metadata properties:
ab.entry_id
ab.pdb_id
ab.split
ab.is_synthetic
ab.is_non_redundant
ab.antibody_type
ab.is_scfv
ab.is_engineered
ab.has_antigen
ab.antigen_types
ab.antigen_names
ab.antigen_chain_idsSequence and region helpers:
ab.heavy_sequence
ab.light_sequence
ab.h_cdr1_sequence
ab.h_cdr2_sequence
ab.h_cdr3_sequence
ab.l_cdr1_sequence
ab.l_cdr2_sequence
ab.l_cdr3_sequence
ab.cdrs_sequences
ab.region_sequence("H", "CDR3")
ab.region_indices("L", "FR2")
ab.cdr_edit_distance(other_ab, "H", 3)
ab.variable_region_seq_identity(other_ab)Structure helpers load the PDB/mmCIF file on first use:
structure = ab.load_structure()
heavy_residues = ab.heavy_residues
light_residues = ab.light_residues
antigen_groups = ab.antigen_residues
interface = ab.interface_residues(threshold=5.0)Coordinate helpers return (coords, mask) pairs. CA coordinates have shape [residue, 3]; backbone atom coordinates have shape [residue, atom, 3].
h_ca, h_ca_mask = ab.heavy_ca_coords()
l_ca, l_ca_mask = ab.light_ca_coords()
h_atoms, h_atom_mask = ab.heavy_atom_coords()
l_atoms, l_atom_mask = ab.light_atom_coords()
ag_ca_list, ag_ca_mask_list = ab.antigen_ca_coords()from torch.utils.data import DataLoader
from sable import TorchSableDataset
from sable.collate import collate_antibodies
from sable.transforms import ToCACoords
train = TorchSableDataset(
root="~/data/sable",
split="train",
synthetic=False,
non_redundant=True,
has_aa_antigen_only=True,
transform=ToCACoords(include_antigen=True),
)
loader = DataLoader(
train,
batch_size=8,
shuffle=True,
num_workers=4,
collate_fn=collate_antibodies,
)
batch = next(iter(loader))
print(batch["h_coords"].shape)
print(batch["h_mask"].shape)
print(batch["l_coords"].shape)
print(batch["l_mask"].shape)
print(batch["ag_coords"].shape)
print(batch["ag_mask"].shape)ToCACoords and ToBackboneAtoms return separate heavy-chain, light-chain, and antigen coordinate fields. collate_antibodies pads variable-length tensors and concatenates all antigen chains for each entry into one antigen tensor before batching.
The Zenodo record contains flat files such as:
sable_v0.1.0_README.md
sable_v0.1.0_metadata.csv
sable_v0.1.0_metadata.parquet
sable_v0.1.0_metadata_schema.json
sable_v0.1.0_column_descriptions.md
sable_v0.1.0_splits.zip
sable_v0.1.0_sequences.zip
sable_v0.1.0_structures_pdb_000.tar.gz
sable_v0.1.0_manifest.json
sable_v0.1.0_checksums.sha256
sable_v0.1.0_LICENSE-DATA.txt
sable_v0.1.0_VALIDATION_REPORT.md
The package extracts those files into a local release tree:
sable_v0.1.0/
metadata/
metadata.csv
metadata.parquet
metadata_schema.json
column_descriptions.md
splits/default/
train.txt
test.txt
train_experimental.txt
synthetic.txt
train_experimental_non_redundant.txt
train_experimental_non_redundant_and_synthetic.txt
train_experimental_redundant.json
sequences/
heavy.fasta
light.fasta
paired_variable_domains.fasta
structures/pdb/
<entry_id>.pdb
manifest.json
checksums.sha256
README.md
LICENSE-DATA.txt
Download from Zenodo and create the release tree:
sable-download \
--root ~/data/sable \
--version 0.1.0 \
--record-id 20809003Extract from an already downloaded flat Zenodo folder:
sable-extract-release \
--zenodo-upload /path/to/zenodo_upload \
--out ~/data/sable \
--version 0.1.0Validate a release tree:
sable-validate ~/data/sable/sable_v0.1.0Summarize a release tree or metadata file:
sable-summary ~/data/sable/sable_v0.1.0
sable-summary ~/data/sable/sable_v0.1.0 --json
sable-summary ~/data/sable/sable_v0.1.0 --check-structuressable.evaluation contains core metrics for antibody-structure benchmark evaluation. The functions work on NumPy-like coordinate arrays, and several helpers accept Antibody-like objects that expose the SABLE coordinate API.
from sable.evaluation import (
aligned_rmsd,
antibody_chain_aligned_rmsd,
cdr_rmsd_after_framework_alignment,
dockq,
dockq_score,
evaluate_antibody_prediction,
sequence_recovery,
)
heavy_rmsd = antibody_chain_aligned_rmsd(reference_ab, predicted_ab, chain="H")
h3_rmsd = cdr_rmsd_after_framework_alignment(reference_ab, predicted_ab, chain="H", cdr=3)
recovery = sequence_recovery(reference_ab.heavy_sequence, predicted_ab.heavy_sequence)
all_metrics = evaluate_antibody_prediction(reference_ab, predicted_ab)For docking-style antibody-antigen scoring, pass receptor and ligand residue coordinates:
scores = dockq(
reference_receptor_coords,
reference_ligand_coords,
predicted_receptor_coords,
predicted_ligand_coords,
)
print(scores["dockq"], scores["fnat"], scores["interface_rmsd"], scores["ligand_rmsd"])If you use SABLE, cite the SABLE dataset DOI, the SABLE paper, and the source PDB/SAbDab resources.
The Python package is released under the MIT license. The dataset itself is under the data license specified in the Zenodo record and LICENSE-DATA.txt.
