Add mmCIF/PDBx (efCIF) structure and trajectory I/O

Add mmCIF/PDBx (efCIF) structure and trajectory I/O

Summary

Adds a new efCIF file type so GROMACS can read and write mmCIF/PDBx structure files, and correctly handle the extended identifier formats the format carries (PDB ID & CCD codes). mmCIF/PDBx is now the primary wwPDB distribution format, and this is a step toward the unified-I/O framework discussed upstream.

What this enables

  • gmx editconf, pdb2gmx, grompp -c, etc. can read/write .cif.
  • gmx trjconv can read a multi-model .cif as a trajectory and write one.
  • The extended PDB entry id (pdb_########, up to 12 chars) is read from _entry.id into the structure name without truncation.
  • Expanded component/ligand ids (up to 5-char CCD codes) are preserved in residue names.
  • With -conect, atom connectivity is written as struct_conn records — the mmCIF counterpart of the PDB LINK/SSBOND records — and read back again.
  • Cis peptide bonds found in the coordinates are annotated in struct_mon_prot_cis.
  • -w can now display .cif (and .gro) files.

Design

Reading / writing (src/gromacs/fileio/cifio.{h,cpp})

  • A self-contained CifIO class wraps the bundled RCSB parser. It maps the atom_site records and unit cell to GROMACS t_atoms/x/box/PbcType, and back, reusing the existing cell:left_right_arrow:matrix math and symtab interning.
  • The mmCIF-library headers are confined to cifio.cpp; cifio.h exposes no third-party types, so the reader/writer is a drop-in format plugin for a future unified-I/O framework (#5154) rather than added coupling.
  • Wired into the existing confio.cpp structure-I/O dispatch and, for multi-model files, the trxio.cpp trajectory framework + trjconv.
  • Reading/writing needs no dictionary — CIF is self-describing; the ~18 standardized atom_site/cell/entry item names are used directly.

Connectivity and cis-peptide annotation

  • The PDB CONECT record has no mmCIF equivalent — every field maps to n.a. in the wwPDB PDB/PDBx correspondence. Connectivity is instead expressed by struct_conn, onto which LINK and SSBOND map, so that is what the bonds of a gmx_conect are written as, typed covale or disulf.
  • Writing every bond, rather than only those not implied by the chemical component dictionary, goes beyond how the PDB uses struct_conn. It is deliberate, so that -conect means the same thing for mmCIF as for PDB output, where GROMACS likewise writes every bond.
  • CISPEP maps to struct_mon_prot_cis. This is a geometric annotation of the coordinates at hand, which for a simulation snapshot may legitimately differ from the records of the entry it started from.

Bundled library (src/external/mmcif-dict-suite/, upstream 2.50.11)

  • A trimmed subset of the RCSB mmCIF Dictionary Suite — only the CIF parser/table/file modules — built into a single static mmcif library by a GROMACS-owned CMakeLists.txt.
  • Vendored per module, pinned to specific upstream commits rather than to a release number; UPDATING.md carries the commit table and the refresh procedure.
  • The flex/bison parser output is committed (generated/), so the build needs no flex, bison, or python and performs no network access. The upstream dictionary-download/validation/CPack machinery is dropped.
  • No local patches. The sources are pristine upstream, file for file. Two changes were carried here while they were in review upstream — replacing the std::bind2nd / std::not1 binders and the std::unary_function / std::binary_function bases that C++17 removed, and annotating harmless deadcode.DeadStores for the Clang-analyzer CI job. Both were accepted upstream (rcsb/cpp-common#1, rcsb/cpp-tables#1, rcsb/cpp-cif-file#2) and the pinned commits contain them, so the local copies have been dropped and every [[clang::suppress]] annotation is gone. The binder fix mattered for GROMACS itself, not only for the library: cifio.cpp pulls in GenString.h through CifFile.h, so a libc++ build failed at C++17 and later.

Testing

  • Unit tests in src/gromacs/fileio/tests/:
    • cifio.cpp — structure round trip (coords/box), extended entry-id preservation, 5-char component-name preservation, connectivity round trip, disulfide typing, index filtering, alt-loc/entity columns, and cis/trans peptide annotation including the sign of pdbx_omega_angle.
    • cifio_trajectory.cpp — two-model write/read round trip, empty-file guard, connectivity written once for all models.
    • filetypes.cpp updated for the new efCIF enum value.
  • Full fileio unit-test suite passes (475 tests), along with tool, gmxpreprocess and commandline.
  • Validated against an independent parser: gemmi reads the written files back, which is how a missing _atom_site.label_alt_id/label_entity_id pair was caught — GROMACS could re-read its own output, but gemmi read no atoms from it.
  • Manually validated with mmCIF→GRO, PDB→mmCIF→GRO, XTC→multi-model mmCIF, and mmCIF→mmCIF round trips preserving atoms, coordinates, box, and the extended id; -conect output checked to carry the same bond count as the equivalent PDB CONECT run.

Scope / follow-ups (not in this MR)

Filed as issues so they are tracked rather than lost:

  • #5673 (closed) — drop the vendored patches once the upstream PRs merge.
  • #5674 — sequential/streaming parsing of very large CIF files (needs an upstream Parse(FILE*) overload).
  • #5675 — allow building against a system-installed suite, once upstream ships an installable package.
  • #5676 — group bundled external targets under an IDE folder.
  • #5677 — chain identifiers longer than one character are truncated on read; t_resinfo::chainid is a single char.
  • #5678 — mmCIF I/O holds the whole file in memory, and parses it twice on read.
  • #5680 — files with loop values after a closing semicolon cannot be read; a bug in the vendored parser, fix in progress upstream.

Also future work: the broader I/O-framework restructure (#5154), dictionary-based validation (intentionally out of scope — the reader/writer does not need the .dic; if added later it should be an installed runtime data file, not an embedded binary), and ligand/residue topology from the Chemical Component Dictionary.

Notes for reviewers

  • Adding efCIF mid-enum shifts later GromacsFileType values; the only place that hard-codes them (tests/filetypes.cpp) is updated accordingly.
  • efCIF is registered in the structure and trajectory filetype groups.
  • The connectivity read path has no in-tree consumer yet — GROMACS never fills a gmx_conect from a file — and exists for round-trip correctness and future use.
  • -conect skips bonds whose partner is outside an index selection. The PDB writer does not do this, so indexed mmCIF output is slightly more correct than its PDB counterpart here.
Edited by Amr ALHOSSARY

Merge request reports

Loading
Loading