feat: Add mmCIF file support for macromolecular structures#7925
feat: Add mmCIF file support for macromolecular structures#7925behroozazarkhalili wants to merge 5 commits into
Conversation
|
Hi ! is there a lib in python that parses the text of the files ? Maybe it would be more useful to return a parsed object rather than just the data as string (and sorry for the delay reveiwing this !) |
Add support for loading mmCIF (macromolecular Crystallographic Information File) format directly with load_dataset(). mmCIF is the modern standard for 3D macromolecular structures used by PDB since 2014. Key features: - Zero external dependencies: Pure Python parser for CIF syntax - Streaming support: Generator-based parsing for large structure files - Compression support: Auto-detection of gzip, bzip2, xz compressed files - ML-ready output: Atomic coordinates suitable for structure-based ML models Configuration options: - columns: Select subset of atom_site columns (default: 11 common columns) - include_hetatm: Option to exclude ligand/water HETATM records - batch_size: Control atoms per batch (default: 100000) Supported extensions: .cif, .mmcif (and compressed variants)
This refactors the mmCIF loader to follow the ImageFolder pattern, where
each row in the dataset contains one complete protein structure file.
This is the recommended ML-friendly approach for working with structural data.
Key changes:
- Add ProteinStructure feature type for handling protein structure files
- Supports lazy loading (decode=False) or full content (decode=True)
- Works with both PDB and mmCIF formats
- Rewrite MmcifFolder to extend FolderBasedBuilder
- Supports folder-based labels (like ImageFolder)
- Supports metadata.csv files for additional columns
- Uses ProteinStructure as BASE_FEATURE
- Fix bug in FolderBasedBuilder._generate_examples where drop_metadata
would fail with IndexError when metadata files were in the files list
- Root cause: enumerate(files) created gaps in shard_idx when files
were skipped due to extension filtering
- Solution: Use separate valid_shard_idx counter that only increments
when samples are actually yielded
Usage:
>>> from datasets import load_dataset
>>> dataset = load_dataset("mmcif", data_dir="./structures")
>>> structure_content = dataset[0]["structure"] # Complete mmCIF content
- Fix line length in protein_structure.py error messages - Sort imports alphabetically in __init__.py - Format function calls and f-strings in test_mmcif.py
…ote_files API The embed_storage API gained local_files and remote_files parameters (v4.8.5) to gate which paths are embedded into the Arrow array. ProteinStructure was written before this change and broke under the current embed_array_storage call path (TypeError: unexpected keyword argument 'local_files'). Align its signature and gating logic with the other binary features (Pdf/Image), embedding local paths only when local_files is set and remote URLs only when remote_files is set.
b96b3f8 to
84c9892
Compare
|
Hi @lhoestq, thanks — and no worries about the delay! Good questions. Quick status + a proposal: On a parsing library: there are mature options — gemmi, biotite, and Biopython all parse mmCIF/PDB. The catch is they're all compiled/heavyweight dependencies (Biopython is ~150 MB installed; gemmi and biotite ship C/C++ extensions), which is a lot to pull into On returning a parsed object instead of a string: agreed — and that's actually a regression I introduced. The original version of this PR parsed Proposal — combine both so each row is one structure and a parsed object, with no new dependency:
That keeps it queryable and ML-friendly while staying dependency-free. Does that direction work for you? Happy to expose the raw bytes alongside the parsed fields if you think both are useful. |
Decoding a ProteinStructure now returns a struct-of-arrays of atom-level
columns parsed from the mmCIF _atom_site loop, keyed by PDBx/mmCIF dictionary
names (type_symbol, label_atom_id, label_comp_id, label_asym_id, label_seq_id,
Cartn_x/y/z, occupancy, B_iso_or_equiv), while keeping one row per structure.
PDB- and mmCIF-derived datasets share the same column vocabulary.
The shared parser lives in features/protein_parsing.py (single canonical
column/dtype table reused by both formats). ProteinStructure parses lazily on
decode (mirroring the Image/Audio/Mesh features); decode=False still returns
the raw {path, bytes} mapping for a custom parser. New feature/config options
include_hetatm and columns are threaded through a _base_feature() factory on
FolderBasedBuilder so folder loaders can forward config-derived arguments to
their base feature. Docs updated to match the new API.
|
Hi @lhoestq — following up on the parsed-object direction we discussed. I've implemented it. Each row is still one structure (one row = one structure, per #7930), but the >>> ds = load_dataset("mmcif", data_dir="structures")
>>> ds[0]["structure"]
{'type_symbol': ['N', 'C', ...], 'label_atom_id': ['N', 'CA', ...],
'label_comp_id': ['ALA', 'ALA', ...], 'label_asym_id': ['A', 'A', ...],
'label_seq_id': [1, 1, ...], 'Cartn_x': [0.0, 1.458, ...],
'Cartn_y': [...], 'Cartn_z': [...], 'occupancy': [...], 'B_iso_or_equiv': [...]}Design notes:
All existing tests pass and I added coverage for the parsed schema, the HETATM filter, and column selection. Docs in |
|
I feel like it would be better for people to extend the parsing and to add useful processing methods if the decoding returns an object like a biopython structure (esp. since the community has been contributing to biopython mostly so they can contribute there). IMO It's ok if the dependency is not that lightweight, what matters the most is to get an object that users can easily process/convert/prepare to train models |
Summary
This PR adds support for loading mmCIF (macromolecular Crystallographic Information File) files with
load_dataset(), following the ImageFolder pattern where one row = one structure.Based on feedback from @lhoestq in #7930, this approach makes datasets more practical for ML workflows:
Architecture
Uses
FolderBasedBuilderpattern (likeImageFolder,AudioFolder):New
ProteinStructureFeature TypeSupported Extensions
.cif,.mmcifUsage
Test Results
All 24 mmCIF tests + 15 ProteinStructure feature tests pass.
Related PRs
References
cc @lhoestq @georgia-hf